Skip to content

Commit

Permalink
Copy files for sandbox to isolate dir and back
Browse files Browse the repository at this point in the history
  • Loading branch information
SemaiCZE committed Apr 5, 2018
1 parent dbfaa44 commit 389931f
Show file tree
Hide file tree
Showing 17 changed files with 94 additions and 59 deletions.
6 changes: 3 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ endif()
set (Boost_USE_MULTITHREADED ON)
find_package(Boost 1.53.0 REQUIRED COMPONENTS filesystem system program_options)
include_directories(${Boost_INCLUDE_DIRS})

# -- cURL
find_package(CURL REQUIRED)
include_directories(${CURL_INCLUDE_DIRS})
Expand Down Expand Up @@ -63,10 +63,10 @@ endif()


# -- ZeroMQ on Windows
if(MSVC)
if(MSVC)
find_path(ZEROMQ_INCLUDE NAMES zmq.h PATHS ${ZMQ_INCLUDE_DIR})
find_library(ZEROMQ_LIB NAMES libzmq PATHS ${ZMQ_LIBRARY_DIR})

if(ZEROMQ_LIB)
include_directories(${ZEROMQ_INCLUDE})
else()
Expand Down
4 changes: 2 additions & 2 deletions recodex-worker.spec
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
%define name recodex-worker
%define short_name worker
%define version 1.3.0
%define unmangled_version ba766e3b1ae62ea23334f7b242f6c63764528790
%define release 5
%define unmangled_version 51f034c148874203a8230043e6c572805a044bd0
%define release 2

%define spdlog_name spdlog
%define spdlog_version 0.13.0
Expand Down
3 changes: 1 addition & 2 deletions src/config/sandbox_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class sandbox_config
* Change working directory to subdirectory inside the sandbox.
* @note Path must be accessible from inside of sandbox.
*/
std::string chdir;
std::string chdir = "";
/**
* Associative array of loaded limits with textual index identifying its hw group.
*/
Expand All @@ -50,7 +50,6 @@ class sandbox_config
*/
sandbox_config()
{
chdir = "${EVAL_DIR}";
}
};

Expand Down
2 changes: 0 additions & 2 deletions src/config/sandbox_limits.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,6 @@ struct sandbox_limits {
*/
sandbox_limits()
{
bound_dirs.push_back(std::tuple<std::string, std::string, sandbox_limits::dir_perm>(
"${SOURCE_DIR}", "${EVAL_DIR}", dir_perm::RW));
}

/**
Expand Down
9 changes: 6 additions & 3 deletions src/config/task_metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ class task_metadata
task_type type = task_type::INNER,
std::string cmd = "",
std::vector<std::string> args = {},
std::shared_ptr<sandbox_config> sandbox = nullptr)
: task_id(task_id), priority(priority), fatal_failure(fatal), dependencies(deps), type(type), binary(cmd),
cmd_args(args), sandbox(sandbox)
std::shared_ptr<sandbox_config> sandbox = nullptr,
std::string test_id = "")
: task_id(task_id), priority(priority), fatal_failure(fatal), dependencies(deps), test_id(test_id), type(type),
binary(cmd), cmd_args(args), sandbox(sandbox)
{
}

Expand All @@ -48,6 +49,8 @@ class task_metadata
bool fatal_failure;
/** Dependent tasks which have to be executed before this one. */
std::vector<std::string> dependencies;
/** Test id for external tasks */
std::string test_id;

/** Type of this task. */
task_type type;
Expand Down
3 changes: 3 additions & 0 deletions src/helpers/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ std::shared_ptr<job_metadata> helpers::build_job_metadata(const YAML::Node &conf
} else {
throw config_exception("Configuration of one task has missing cmd");
}
if (ctask["test-id"] && ctask["test-id"].IsScalar()) {
task_meta->test_id = ctask["test-id"].as<std::string>();
}

// load dependencies
if (ctask["dependencies"] && ctask["dependencies"].IsSequence()) {
Expand Down
4 changes: 1 addition & 3 deletions src/helpers/filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ void helpers::copy_directory(const fs::path &src, const fs::path &dest)
throw filesystem_exception("Source directory does not exist");
} else if (!fs::is_directory(src)) {
throw filesystem_exception("Source directory is not a directory");
} else if (fs::exists(dest)) {
throw filesystem_exception("Destination directory exists");
} else if (!fs::create_directories(dest)) {
} else if (!fs::exists(dest) && !fs::create_directories(dest)) {
throw filesystem_exception("Destination directory cannot be created");
}

Expand Down
11 changes: 7 additions & 4 deletions src/helpers/format.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@

#include <sstream>

namespace helpers {
inline void format(std::ostringstream &) {}
namespace helpers
{
inline void format(std::ostringstream &)
{
}

template<typename ArgT, typename...T>
void format(std::ostringstream &oss, const ArgT &a, T...args) {
template <typename ArgT, typename... T> void format(std::ostringstream &oss, const ArgT &a, T... args)
{
oss << a;
format(oss, args...);
}
Expand Down
62 changes: 45 additions & 17 deletions src/sandbox/isolate_sandbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,48 @@
#define BOOST_FILESYSTEM_NO_DEPRECATED
#define BOOST_NO_CXX11_SCOPED_ENUMS
#include <boost/filesystem.hpp>
#include "../helpers/filesystem.h"

namespace fs = boost::filesystem;

namespace
{
void move_or_throw(std::shared_ptr<spdlog::logger> logger, const std::string &from, const std::string &to)
{
try {
helpers::copy_directory(from, to);
} catch (fs::filesystem_error &e) {
log_and_throw(logger, "Failed moving ", from, " to ", to, ", error: ", e.what());
}

try {
fs::remove_all(from);
} catch (fs::filesystem_error &) {
}
}
}

isolate_sandbox::isolate_sandbox(std::shared_ptr<sandbox_config> sandbox_config,
sandbox_limits limits,
size_t id,
const std::string &temp_dir,
const std::string &data_dir,
std::shared_ptr<spdlog::logger> logger)
: sandbox_config_(sandbox_config), limits_(limits), logger_(logger), id_(id), isolate_binary_("isolate")
: sandbox_config_(sandbox_config), limits_(limits), logger_(logger), id_(id), isolate_binary_("isolate"),
data_dir_(data_dir)
{
if (sandbox_config == nullptr) {
throw sandbox_exception("No sandbox configuration provided.");
}

if (logger_ == nullptr) {
logger_ = helpers::create_null_logger();
}

if (sandbox_config_ == nullptr) {
log_and_throw(logger_, "No sandbox configuration provided.");
}

if (data_dir_ == "") {
logger_->info("Empty data directory for moving to sandbox.");
}

// Set backup limit (for killing isolate if it hasn't finished yet)
max_timeout_ = limits_.wall_time > limits_.cpu_time ? limits_.wall_time : limits_.cpu_time;
max_timeout_ += 300; // plus 5 minutes (for short tasks)
Expand Down Expand Up @@ -69,7 +92,19 @@ isolate_sandbox::~isolate_sandbox()

sandbox_results isolate_sandbox::run(const std::string &binary, const std::vector<std::string> &arguments)
{
// move data to isolate directory
if (data_dir_ != "") {
move_or_throw(logger_, data_dir_, sandboxed_dir_);
}

// run isolate
isolate_run(binary, arguments);

// move data from isolate directory back to data directory
if (data_dir_ != "") {
move_or_throw(logger_, sandboxed_dir_, data_dir_);
}

return process_meta_file();
}

Expand All @@ -88,9 +123,7 @@ void isolate_sandbox::isolate_init()
childpid = fork();

switch (childpid) {
case -1:
log_and_throw(logger_, "Fork failed: ", strerror(errno));
break;
case -1: log_and_throw(logger_, "Fork failed: ", strerror(errno)); break;
case 0: isolate_init_child(fd[0], fd[1]); break;
default:
//---Parent---
Expand All @@ -105,6 +138,7 @@ void isolate_sandbox::isolate_init()
}
sandboxed_dir_ += std::string(buf);
}
sandboxed_dir_ += "/box";
if (ret == -1) {
log_and_throw(logger_, "Read from pipe error.");
}
Expand Down Expand Up @@ -161,9 +195,7 @@ void isolate_sandbox::isolate_cleanup()
childpid = fork();

switch (childpid) {
case -1:
log_and_throw(logger_, "Fork failed: ", strerror(errno));
break;
case -1: log_and_throw(logger_, "Fork failed: ", strerror(errno)); break;
case 0:
//---Child---
// Redirect stderr to /dev/null file
Expand Down Expand Up @@ -209,9 +241,7 @@ void isolate_sandbox::isolate_run(const std::string &binary, const std::vector<s
childpid = fork();

switch (childpid) {
case -1:
log_and_throw(logger_, "Fork failed: ", strerror(errno));
break;
case -1: log_and_throw(logger_, "Fork failed: ", strerror(errno)); break;
case 0: {
//---Child---
logger_->debug("Returned from the first fork as child");
Expand Down Expand Up @@ -245,9 +275,7 @@ void isolate_sandbox::isolate_run(const std::string &binary, const std::vector<s
logger_->debug("Running the second fork");
controlpid = fork();
switch (controlpid) {
case -1:
log_and_throw(logger_, "Fork failed: ", strerror(errno));
break;
case -1: log_and_throw(logger_, "Fork failed: ", strerror(errno)); break;
case 0:
// Child---
{
Expand Down
4 changes: 4 additions & 0 deletions src/sandbox/isolate_sandbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,14 @@ class isolate_sandbox : public sandbox_base
* @param limits Limits for current command.
* @param id Number of current worker. This must be unique for each worker on one machine!
* @param temp_dir Directory to store temporary files (generated isolate's meta log)
* @param data_dit Directory containing sources which will be copied into sandbox
* @param logger Set system logger (optional).
*/
isolate_sandbox(std::shared_ptr<sandbox_config> sandbox_config,
sandbox_limits limits,
size_t id,
const std::string &temp_dir,
const std::string &data_dir,
std::shared_ptr<spdlog::logger> logger = nullptr);
/**
* Destructor.
Expand All @@ -66,6 +68,8 @@ class isolate_sandbox : public sandbox_base
std::string meta_file_;
/** Maximum time to run separate isolate process */
int max_timeout_;
/** Path to the directory containing sources moved to sandbox and back */
std::string data_dir_;
/** Initialize isolate */
void isolate_init();
/** Actual code for isolate initialization inside a process. Called by isolate_init(). */
Expand Down
4 changes: 2 additions & 2 deletions src/sandbox/sandbox_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ class sandbox_exception : public std::exception
};


template<typename...T>
void log_and_throw(std::shared_ptr<spdlog::logger> logger, T...args) {
template <typename... T> void log_and_throw(std::shared_ptr<spdlog::logger> logger, T... args)
{
std::ostringstream oss;
helpers::format(oss, args...);
const auto message = oss.str();
Expand Down
3 changes: 2 additions & 1 deletion src/tasks/external_task.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ void external_task::sandbox_init()
{
#ifndef _WIN32
if (task_meta_->sandbox->name == "isolate") {
auto data_dir = fs::path(source_dir_) / task_meta_->test_id;
sandbox_ = std::make_shared<isolate_sandbox>(
sandbox_config_, *limits_, worker_config_->get_worker_id(), temp_dir_, logger_);
sandbox_config_, *limits_, worker_config_->get_worker_id(), temp_dir_, data_dir.string(), logger_);
}
#endif
}
Expand Down
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ add_test_suite(tool_isolate_sandbox
isolate_sandbox.cpp
${SANDBOX_DIR}/isolate_sandbox.cpp
${HELPERS_DIR}/logger.cpp
${HELPERS_DIR}/filesystem.cpp
)

add_test_suite(tool_archivator
Expand Down
4 changes: 2 additions & 2 deletions tests/build_job_metadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,10 @@ TEST(job_metadata, build_all_from_yaml)
auto envs = std::pair<std::string, std::string>{"ISOLATE_TMP", "/tmp"};
EXPECT_EQ(envs, limits->environ_vars[0]);

EXPECT_EQ(2u, limits->bound_dirs.size());
EXPECT_EQ(1u, limits->bound_dirs.size());
auto dirs = std::tuple<std::string, std::string, sandbox_limits::dir_perm>{
"path1/dir1", "path2/dir2", sandbox_limits::dir_perm::RW};
EXPECT_EQ(dirs, limits->bound_dirs[1]);
EXPECT_EQ(dirs, limits->bound_dirs[0]);
}

TEST(job_metadata, queue_of_tasks)
Expand Down
28 changes: 13 additions & 15 deletions tests/isolate_sandbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ TEST(IsolateSandbox, BasicCreation)
{
std::shared_ptr<sandbox_config> config = std::make_shared<sandbox_config>();
sandbox_limits limits;
EXPECT_NO_THROW(isolate_sandbox s(config, limits, 34, "/tmp"));
isolate_sandbox is(config, limits, 34, "/tmp");
EXPECT_EQ(is.get_dir(), "/var/local/lib/isolate/34");
EXPECT_THROW(isolate_sandbox s(config, limits, 2365, "/tmp"), sandbox_exception);
EXPECT_NO_THROW(isolate_sandbox s(config, limits, 34, "/tmp", ""));
isolate_sandbox is(config, limits, 34, "/tmp", "");
EXPECT_EQ(is.get_dir(), "/var/local/lib/isolate/34/box");
EXPECT_THROW(isolate_sandbox s(config, limits, 2365, "/tmp", ""), sandbox_exception);
}

TEST(IsolateSandbox, NormalCommand)
Expand All @@ -42,8 +42,8 @@ TEST(IsolateSandbox, NormalCommand)
limits.share_net = false;
limits.bound_dirs.clear();
isolate_sandbox *is = nullptr;
EXPECT_NO_THROW(is = new isolate_sandbox(config, limits, 34, "/tmp"));
EXPECT_EQ(is->get_dir(), "/var/local/lib/isolate/34");
EXPECT_NO_THROW(is = new isolate_sandbox(config, limits, 34, "/tmp", ""));
EXPECT_EQ(is->get_dir(), "/var/local/lib/isolate/34/box");
sandbox_results results;
EXPECT_NO_THROW(results = is->run("/bin/ls", std::vector<std::string>{"-a", "-l", "-i"}));
EXPECT_TRUE(fs::is_regular_file("/var/local/lib/isolate/34/box/output.txt"));
Expand Down Expand Up @@ -77,8 +77,8 @@ TEST(IsolateSandbox, TimeoutCommand)
limits.share_net = false;
limits.bound_dirs.clear();
isolate_sandbox *is = nullptr;
EXPECT_NO_THROW(is = new isolate_sandbox(config, limits, 34, "/tmp"));
EXPECT_EQ(is->get_dir(), "/var/local/lib/isolate/34");
EXPECT_NO_THROW(is = new isolate_sandbox(config, limits, 34, "/tmp", ""));
EXPECT_EQ(is->get_dir(), "/var/local/lib/isolate/34/box");
sandbox_results results;
EXPECT_NO_THROW(results = is->run("/bin/sleep", std::vector<std::string>{"5"}));
EXPECT_TRUE(fs::is_regular_file("/tmp/34/meta.log"));
Expand Down Expand Up @@ -110,8 +110,8 @@ TEST(IsolateSandbox, NonzeroReturnCommand)
limits.share_net = false;
limits.bound_dirs.clear();
isolate_sandbox *is = nullptr;
EXPECT_NO_THROW(is = new isolate_sandbox(config, limits, 34, "/tmp"));
EXPECT_EQ(is->get_dir(), "/var/local/lib/isolate/34");
EXPECT_NO_THROW(is = new isolate_sandbox(config, limits, 34, "/tmp", ""));
EXPECT_EQ(is->get_dir(), "/var/local/lib/isolate/34/box");
sandbox_results results;
EXPECT_NO_THROW(results = is->run("/bin/false", std::vector<std::string>{}));
EXPECT_TRUE(fs::is_regular_file("/tmp/34/meta.log"));
Expand Down Expand Up @@ -150,17 +150,15 @@ TEST(IsolateSandbox, NonzeroReturnCommand)

TEST(IsolateSandbox, BindDirsExecuteGCC)
{
using sp = sandbox_limits::dir_perm;
auto tmp = fs::temp_directory_path();
std::shared_ptr<sandbox_config> config = std::make_shared<sandbox_config>();
config->chdir = "evaluate";
config->chdir = "";
sandbox_limits limits;
limits.wall_time = 10;
limits.cpu_time = 10;
limits.extra_time = 1;
limits.processes = 0;
limits.bound_dirs = {
std::tuple<std::string, std::string, sp>{(tmp / "recodex_35_test").string(), "evaluate", sp::RW}};
limits.bound_dirs = {};
limits.environ_vars = {{"PATH", "/usr/bin"}};

fs::create_directories(tmp / "recodex_35_test");
Expand All @@ -171,7 +169,7 @@ TEST(IsolateSandbox, BindDirsExecuteGCC)
}

isolate_sandbox *is = nullptr;
EXPECT_NO_THROW(is = new isolate_sandbox(config, limits, 35, "/tmp"));
EXPECT_NO_THROW(is = new isolate_sandbox(config, limits, 35, tmp.string(), (tmp / "recodex_35_test").string()));
sandbox_results results;
EXPECT_NO_THROW(results = is->run("/usr/bin/gcc", std::vector<std::string>{"-Wall", "-o", "test", "main.c"}));

Expand Down
Loading

0 comments on commit 389931f

Please sign in to comment.