diff --git a/.gitignore b/.gitignore index bbf313b25987d0d61b1cea33a8e6188501e221ac..acdbda377fcc9811175145b0f3be96a5498e7f8e 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,13 @@ # Debug files *.dSYM/ + +Makefile +Makefile.in +aclocal.m4 +autom4te.cache +config.log +config.status +configure +libtool +m4 diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..cc5f263782ac2a0a760d51a59012e7dcbe3a24de --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,5 @@ +.deps +argo_nodeos_config +config.h +config.h.in +stamp-h1 diff --git a/src/argo_nodeos_config.cpp b/src/argo_nodeos_config.cpp index 00926e6061bf259c8a7d0ec1e833bbf7ff59160c..6fc22eec8e6929da3c9086128f03c25d5bfa7ca0 100644 --- a/src/argo_nodeos_config.cpp +++ b/src/argo_nodeos_config.cpp @@ -524,7 +524,10 @@ enum Option_val OV_DELETE_SERVICE_OS, - OV_RESET + OV_RESET, + + /*--exec="name:'c0' argv='argv0 argv1'"*/ + OV_EXEC }; @@ -546,6 +549,7 @@ struct option long_options[] = { {"detach_from_container", required_argument, NULL, OV_DETACH_FROM_CONTAINER}, {"migrate_to_container", required_argument, NULL, OV_MIGRATE_TO_CONTAINER}, {"reset", no_argument, NULL, OV_RESET}, + {"exec", required_argument, NULL, OV_EXEC}, {0, 0, 0, 0} }; @@ -683,6 +687,9 @@ bool parse_for_node_config(int argc, char** argv, Container_manager& cm) case OV_RESET: cm.reset(); break; + case OV_EXEC: + cm.exec(optarg); + break; case '?': case ':': cmd_error = true; @@ -757,10 +764,19 @@ int main(int argc, char** argv) argo_exit(EXIT_FAILURE, e.what()); } + char** exec_argv = cm->get_exec_argv(); delete cm; rlock.unlock(); release(); + + /* We perform the execve(2) after all the cleanup is done. */ + if (exec_argv) + { + execvp(exec_argv[0], exec_argv); + argo_exit(EXIT_FAILURE, "Command execution failed", errno); + } + argo_exit(EXIT_SUCCESS); return 0; } diff --git a/src/container_manager.cpp b/src/container_manager.cpp index f830fa243555132b80afa30fe7366bee0df4db28..75bf83268286a17d27b59605146a1ca6b47fb967 100644 --- a/src/container_manager.cpp +++ b/src/container_manager.cpp @@ -275,7 +275,7 @@ void Container_manager::create_root_cgroups() void Container_manager::migrate_service_os() { - system("for t in `cat /sys/fs/cgroup/cpuset/tasks`; do /bin/echo $t > /sys/fs/cgroup/cpuset/argo/service_os/tasks; done 2>/dev/null"); + int n = system("for t in `cat /sys/fs/cgroup/cpuset/tasks`; do /bin/echo $t > /sys/fs/cgroup/cpuset/argo/service_os/tasks; done 2>/dev/null"); return; vector sos_tasks; retrieve_from_file( _cgroup_root + "cpuset/tasks", @@ -375,6 +375,9 @@ void Container_manager::load_existing_containers_as_root() Container_manager::~Container_manager() +#if __cplusplus >= 201103L + noexcept(false) +#endif { std::ofstream ownership_map_file; ownership_map_file.open(OWNERSHIP_MAP); @@ -681,8 +684,8 @@ void Container_manager::alter_service_os(string command) #endif String_parser sp(command); sp.parse(); - vector allowed_keys( - {"cpus", "+cpus", "-cpus", "mems", "+mems", "-mems", "mem_migrate"}); + const char* initkeys[] = {"cpus", "+cpus", "-cpus", "mems", "+mems", "-mems", "mem_migrate"}; + vector allowed_keys(initkeys, initkeys + sizeof(initkeys) / sizeof(initkeys[0])); THROW_ON_BAD_INPUT_IF(sp.has_forbidden_keys(allowed_keys), "Invalid service_os alteration command"); @@ -766,7 +769,8 @@ void Container_manager::create_service_os(string command) "The node already has a service_os"); String_parser sp(command); sp.parse(); - vector allowed_keys({"cpus", "mems"}); + const char* initkeys[] = {"cpus", "mems"}; + vector allowed_keys(initkeys, initkeys + sizeof(initkeys) / sizeof(initkeys[0])); THROW_ON_BAD_INPUT_IF(sp.has_forbidden_keys(allowed_keys), "Invalid service_os creation command"); @@ -853,7 +857,7 @@ void Container_manager::reset() clean_config(""); /*Temporary ugly brutal hack [JZ] (\_/)*/ - system("rmdir /sys/fs/cgroup/cpuset/argo/argo_containers/ && rmdir /sys/fs/cgroup/cpuset/argo/"); + int n = system("rmdir /sys/fs/cgroup/cpuset/argo/argo_containers/ && rmdir /sys/fs/cgroup/cpuset/argo/"); } void Container_manager::attach_to_container(string command) @@ -866,7 +870,7 @@ void Container_manager::attach_to_container(string command) string name; sp.get_string("name", name); Argo_container *cc = find_by_name(name); - THROW_ON_ERRONEOUS_ACTION_IF(!cc, "Container " + name + "does not exists"); + THROW_ON_ERRONEOUS_ACTION_IF(!cc, "Container " + name + " does not exists"); vector tasks; sp.get_int_list("pids", tasks); @@ -921,7 +925,7 @@ void Container_manager::detach_from_container(string command) string name; sp.get_string("name", name); Argo_container *cc = find_by_name(name); - THROW_ON_ERRONEOUS_ACTION_IF(!cc, "Container " + name + "does not exists"); + THROW_ON_ERRONEOUS_ACTION_IF(!cc, "Container " + name + " does not exists"); vector tasks; sp.get_int_list("pids", tasks); @@ -946,7 +950,7 @@ void Container_manager::migrate_to_container(string command) string name; sp.get_string("name", name); Argo_container *cc = find_by_name(name); - THROW_ON_ERRONEOUS_ACTION_IF(!cc, "Container " + name + "does not exists"); + THROW_ON_ERRONEOUS_ACTION_IF(!cc, "Container " + name + " does not exists"); vector tasks; sp.get_int_list("pids", tasks); @@ -961,12 +965,13 @@ void Container_manager::migrate_to_container(string command) " because it belongs to another user! Alternatively, the action can be performed as root"); std::ostringstream oss; - for(auto task : tasks) + for(vector::iterator task = tasks.begin(); task != tasks.end(); task++) { bool is_task_contained = false; - for(auto cont : _containers) + for(vector::iterator cont = _containers.begin(); + cont != _containers.end(); cont++) { - if(cont->has_task(task)) + if((*cont)->has_task(*task)) { is_task_contained = true; break; @@ -974,7 +979,7 @@ void Container_manager::migrate_to_container(string command) } if(!is_task_contained) { - oss<<"Task "<log(LOG_TYPE_INFO, "Config has been cleaned."); } + +void Container_manager::exec(string command) +{ + String_parser sp(command); + sp.parse(); + + THROW_ON_BAD_INPUT_IF(!sp.has_key("name") || !sp.has_key("argv"), + "Bad exec command"); + string name; + sp.get_string("name", name); + + Argo_container *cc = find_by_name(name); + + THROW_ON_ERRONEOUS_ACTION_IF(!cc, "Container " + name + " does not exists"); + + THROW_ON_FORBIDDEN_ACTION_IF(ruid != 0 && (ruid != cc->get_owner()), + "Can't execute in container " + cc->get_name() + + " because it belongs to another user! Alternatively, the action can be performed as root"); + + string argv; + sp.get_string("argv", argv); + + if (argv[0] == '\'') /* Strip ' from both ends. */ + argv = argv.substr(1, argv.size() - 2); + + vector argvs; + split(argv, ' ', argvs); + + /* Remove a single layer of backslashes. */ + for (vector::iterator i = argvs.begin(); i != argvs.end(); ++i) + for (string::iterator j = i->begin(); j != i->end(); ++j) + if (*j == '\\') + i->erase(j); + + vector tasks(1, getpid()); + cc->add_tasks(tasks); + cc->commit_last_changes(); + + std::ostringstream ss; + ss << "About to execute"; + + /* We use global allocators so that _exec_argv survives after + the container manager is destroyed. */ + _exec_argv = new char*[argvs.size() + 1]; + for (int i = 0; i < argvs.size(); i++) + { + _exec_argv[i] = new char[argvs[i].size() + 1]; + strcpy(_exec_argv[i], argvs[i].c_str()); + ss << " '" << argvs[i] << "'"; + } + _exec_argv[argvs.size()] = NULL; + + _logger->log(LOG_TYPE_INFO, ss.str()); +} diff --git a/src/container_manager.hpp b/src/container_manager.hpp index 754c5e7bb2cd5d947c6650f583a819a3693db9b2..a33a34cd647ce00e7391425e36ebc38fda733dea 100644 --- a/src/container_manager.hpp +++ b/src/container_manager.hpp @@ -33,6 +33,8 @@ class Container_manager string _argo_service_os_cgroup; string _argo_argo_containers_root; + char ** _exec_argv; + Container_manager(Container_manager& orig) = delete; Container_manager& operator = (const Container_manager& orig) = delete; @@ -223,11 +225,16 @@ class Container_manager Container_manager(ILogger* logger, Error_behavior error_behavior, string cgroup_root = DEFAULT_CGROUP_ROOT); - ~Container_manager(); + ~Container_manager() +#if __cplusplus >= 201103L + noexcept(false) +#endif + ; inline const string* const get_argo_argo_container_root() const {return &_cgroup_root;} inline Error_behavior get_error_behaviour()const {return _error_behavior;} inline ILogger* get_logger() const {return _logger;} + inline char** get_exec_argv() const {return _exec_argv;} void show_available_resources(string command); void create_container(string command); @@ -243,6 +250,7 @@ class Container_manager void alter_service_os(string command); void delete_service_os(); void reset(); + void exec(string command); }; #endif // __CONTAINER_MANAGER_HPP__ diff --git a/src/resource_locker.cpp b/src/resource_locker.cpp index 65440718bf66457791d3da60d24e55e404b90383..cf1b4e4435693a2c7eb000033a1d36523f784fac 100644 --- a/src/resource_locker.cpp +++ b/src/resource_locker.cpp @@ -31,7 +31,7 @@ Resource_locker::Resource_locker(const string& filename, const string& path): TRACE_LOC_ON_MASK(RESOURCE_LOCKER_MASK, "euid = %d; ruid = %d\n", geteuid(), getuid()); - _fd = open(fname.c_str(), O_WRONLY|O_CREAT); + _fd = open(fname.c_str(), O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); if(_fd == -1) { argo_exit(EXIT_FAILURE, "Failure to open " + filename); diff --git a/src/syslogger.cpp b/src/syslogger.cpp index 1dc46b3fa471f5ba15c8c81d74c792131a16fd55..047d3c465892c3b722b6684e8677650cde0acfbb 100644 --- a/src/syslogger.cpp +++ b/src/syslogger.cpp @@ -39,5 +39,5 @@ void Syslogger::log(Log_type type, const string& message, int errnum) { string msg_out; if(prepare_log(type, message, msg_out, errnum)) - syslog(log_type_to_priority(type), msg_out.c_str()); + syslog(log_type_to_priority(type), "%s", msg_out.c_str()); } diff --git a/src/utils.cpp b/src/utils.cpp index 5c08579a22efb367de1280f27ddfb53974aa7fae..59f11e73d552b247df15589eae8c9c64534d5428 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -23,6 +23,7 @@ vector &split(const string &str_in, char delim, vector &tokens) { +#if 0 std::stringstream ss(str_in); string token; tokens.clear(); @@ -32,6 +33,9 @@ vector &split(const string &str_in, char delim, vector &tokens) tokens.push_back(token); } return tokens; +#endif + string delims(1, delim); + return split(str_in, delims, tokens); } vector &split(const string &str_in, const string &delims, @@ -49,12 +53,37 @@ vector &split(const string &str_in, const string &delims, for(int i=0; i<(int)delims.size(); i++) { for(int j=start; j