Skip to content

Commit

Permalink
Add working-directory option into sandbox configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
Neloop committed May 10, 2018
1 parent 1ee38fc commit 7333224
Show file tree
Hide file tree
Showing 11 changed files with 70 additions and 6 deletions.
4 changes: 4 additions & 0 deletions src/config/sandbox_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ class sandbox_config
* @note Path must be accessible from inside of sandbox.
*/
std::string chdir = "";
/**
* Working directory relative to the directory with the source files.
*/
std::string working_directory = "";
/**
* Associative array of loaded limits with textual index identifying its hw group.
*/
Expand Down
3 changes: 3 additions & 0 deletions src/helpers/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ std::shared_ptr<job_metadata> helpers::build_job_metadata(const YAML::Node &conf
if (ctask["sandbox"]["chdir"] && ctask["sandbox"]["chdir"].IsScalar()) {
sandbox->chdir = ctask["sandbox"]["chdir"].as<std::string>();
} // can be ommited... no throw
if (ctask["sandbox"]["working-directory"] && ctask["sandbox"]["working-directory"].IsScalar()) {
sandbox->working_directory = ctask["sandbox"]["working-directory"].as<std::string>();
} // can be ommited... no throw

// load limits... if they are supplied
if (ctask["sandbox"]["limits"]) {
Expand Down
15 changes: 15 additions & 0 deletions src/helpers/filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,21 @@ fs::path helpers::normalize_path(const fs::path &path)
return result;
}

bool helpers::check_relative(const fs::path &path) {
if(path.is_absolute()) {
return false;
}

std::vector<fs::path> path_arr(path.begin(), path.end());
for (auto &chunk : path_arr) {
if (chunk.string() == "..") {
return false;
}
}

return true;
}

fs::path helpers::find_path_outside_sandbox(const std::string &inside_path,
const std::string &sandbox_chdir,
std::vector<std::tuple<std::string, std::string, sandbox_limits::dir_perm>> &bound_dirs,
Expand Down
7 changes: 7 additions & 0 deletions src/helpers/filesystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ namespace helpers
*/
fs::path normalize_path(const fs::path &path);

/**
* Check if given path is relative and do not contain any ".." element.
* @param path path to be checked
* @return true if path is relative and without double dots
*/
bool check_relative(const fs::path &path);

/**
* Find path outside sandbox on real filesystem, based on given path inside sandbox.
* @param inside path inside sandbox which will be resolved
Expand Down
5 changes: 5 additions & 0 deletions src/job/job.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ void job::build_job()
limits = std::make_shared<sandbox_limits>(worker_config_->get_limits());
}

// check relativeness of working directory
if (!helpers::check_relative(fs::path(sandbox->working_directory))) {
throw job_exception("Given working directory for task '" + task_meta->task_id + "' is not relative");
}

// go through variables parsing
sandbox->chdir = parse_job_var(sandbox->chdir);
sandbox->std_input = parse_job_var(sandbox->std_input);
Expand Down
1 change: 1 addition & 0 deletions src/job/job.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace fs = boost::filesystem;
#include "spdlog/spdlog.h"
#include "../helpers/logger.h"
#include "../helpers/topological_sort.h"
#include "../helpers/filesystem.h"
#include "../config/worker_config.h"
#include "../config/job_metadata.h"
#include "../config/task_metadata.h"
Expand Down
15 changes: 11 additions & 4 deletions src/tasks/external_task.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace fs = boost::filesystem;
external_task::external_task(const create_params &data)
: task_base(data.id, data.task_meta), worker_config_(data.worker_conf), sandbox_(nullptr),
sandbox_config_(data.task_meta->sandbox), limits_(data.limits), logger_(data.logger), temp_dir_(data.temp_dir),
source_dir_(data.source_path), working_dir_(data.working_path)
evaluation_dir_(data.source_path), working_dir_(data.working_path)
{
if (worker_config_ == nullptr) {
throw task_exception("No worker configuration provided.");
Expand All @@ -27,6 +27,14 @@ external_task::external_task(const create_params &data)
throw task_exception("No sandbox configuration provided.");
}

if (!sandbox_config_->working_directory.empty()) {
if (!helpers::check_relative(sandbox_config_->working_directory)) {
throw task_exception("Given working directory in sandbox config is not relative");
}

evaluation_dir_ = fs::path(data.source_path) / sandbox_config_->working_directory;
}

sandbox_check();
}

Expand All @@ -53,9 +61,8 @@ 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_, data_dir.string(), logger_);
sandbox_config_, *limits_, worker_config_->get_worker_id(), temp_dir_, evaluation_dir_.string(), logger_);
}
#endif
}
Expand Down Expand Up @@ -124,7 +131,7 @@ void external_task::results_output_init()
fs::path external_task::find_path_outside_sandbox(std::string file)
{
return helpers::find_path_outside_sandbox(
file, sandbox_config_->chdir, limits_->bound_dirs, (fs::path(source_dir_) / task_meta_->test_id).string());
file, sandbox_config_->chdir, limits_->bound_dirs, evaluation_dir_.string());
}

void external_task::get_results_output(std::shared_ptr<task_results> result)
Expand Down
4 changes: 2 additions & 2 deletions src/tasks/external_task.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ class external_task : public task_base
std::shared_ptr<spdlog::logger> logger_;
/** Directory for temporary files */
std::string temp_dir_;
/** Directory where source codes for job are located */
fs::path source_dir_;
/** Directory outside sandbox where task will be executed */
fs::path evaluation_dir_;
/** Directory binded to the sandbox as default working dir */
fs::path working_dir_;
/** After execution delete stdout file produced by sandbox */
Expand Down
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ add_test_suite(job
${HELPERS_DIR}/topological_sort.cpp
${HELPERS_DIR}/logger.cpp
${HELPERS_DIR}/config.cpp
${HELPERS_DIR}/filesystem.cpp
${JOB_DIR}/job.cpp
job.cpp
)
Expand Down
18 changes: 18 additions & 0 deletions tests/filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,24 @@ TEST(filesystem_test, normalize)
helpers::normalize_path(fs::path("/first////second/../third/././.")).string());
}

TEST(filesystem_test, test_check_relative)
{
ASSERT_TRUE(helpers::check_relative(fs::path("")));
ASSERT_TRUE(helpers::check_relative(fs::path(".")));
ASSERT_TRUE(helpers::check_relative(fs::path("sth")));
ASSERT_TRUE(helpers::check_relative(fs::path("sth/sth")));
ASSERT_TRUE(helpers::check_relative(fs::path("./sth")));
ASSERT_TRUE(helpers::check_relative(fs::path("./sth/sth")));
ASSERT_FALSE(helpers::check_relative(fs::path("/")));
ASSERT_FALSE(helpers::check_relative(fs::path("/sth")));
ASSERT_FALSE(helpers::check_relative(fs::path("/sth/sth")));
ASSERT_FALSE(helpers::check_relative(fs::path("..")));
ASSERT_FALSE(helpers::check_relative(fs::path("../sth")));
ASSERT_FALSE(helpers::check_relative(fs::path("sth/..")));
ASSERT_FALSE(helpers::check_relative(fs::path("sth/sth/..")));
ASSERT_FALSE(helpers::check_relative(fs::path("sth/sth/../sth")));
}


bound_dirs_type get_default_dirs()
{
Expand Down
3 changes: 3 additions & 0 deletions tests/job_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ TEST(job_config_test, correct_format)
" stdin: 01.in\n"
" stdout: 01.out\n"
" stderr: 01.err\n"
" working-directory: working\n"
" limits:\n"
" - hw-group-id: group1\n"
" time: 5\n"
Expand Down Expand Up @@ -198,6 +199,7 @@ TEST(job_config_test, config_data)
" stdout: 01.out\n"
" stderr: 01.err\n"
" chdir: /eval\n"
" working-directory: working\n"
" limits:\n"
" - hw-group-id: group1\n"
" time: 5\n"
Expand Down Expand Up @@ -253,6 +255,7 @@ TEST(job_config_test, config_data)
ASSERT_EQ(task2->sandbox->std_output, "01.out");
ASSERT_EQ(task2->sandbox->std_error, "01.err");
ASSERT_EQ(task2->sandbox->chdir, "/eval");
ASSERT_EQ(task2->sandbox->working_directory, "working");

ASSERT_EQ(task2->sandbox->loaded_limits.size(), 2u);
EXPECT_NO_THROW(task2->sandbox->loaded_limits.at("group1"));
Expand Down

0 comments on commit 7333224

Please sign in to comment.