From 990e1f3954f8349b9b5ea5d460ec787d19bb381c Mon Sep 17 00:00:00 2001 From: Kamil Iskra Date: Wed, 8 Aug 2018 17:22:57 -0500 Subject: [PATCH] Add a new argument to 'exec' We used to pass the environment for the user job implicitly, as the environment of argo_nodeos_config. This wasn't very clean and was causing problems with, e.g., LD_PRELOAD, which gets filtered out because argo_nodeos_config is suid root. So now we pass the environment as a required, explicit argument. --- src/argo_nodeos_config.cpp | 5 +++-- src/container_manager.cpp | 31 ++++++++++++++++++++++++++++--- src/container_manager.hpp | 2 ++ 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/argo_nodeos_config.cpp b/src/argo_nodeos_config.cpp index 5cbe7ce..4de2f6f 100644 --- a/src/argo_nodeos_config.cpp +++ b/src/argo_nodeos_config.cpp @@ -526,7 +526,7 @@ enum Option_val OV_RESET, - /*--exec="name:'c0' argv='argv0 argv1'"*/ + /*--exec="name:'c0' argv='argv0 argv1'" env='env1=val1 env2=val2'*/ OV_EXEC }; @@ -765,6 +765,7 @@ int main(int argc, char** argv) } char** exec_argv = cm->get_exec_argv(); + char** exec_env = cm->get_exec_env(); delete cm; rlock.unlock(); @@ -775,7 +776,7 @@ int main(int argc, char** argv) { if (setuid(getuid()) == -1) argo_exit(EXIT_FAILURE, "Dropping privileges failed", errno); - execvp(exec_argv[0], exec_argv); + execvpe(exec_argv[0], exec_argv, exec_env); argo_exit(EXIT_FAILURE, "Command execution failed", errno); } diff --git a/src/container_manager.cpp b/src/container_manager.cpp index 75bf832..c657c02 100644 --- a/src/container_manager.cpp +++ b/src/container_manager.cpp @@ -1076,8 +1076,8 @@ 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"); + THROW_ON_BAD_INPUT_IF(!sp.has_key("name") || !sp.has_key("argv") || + !sp.has_key("env"), "Bad exec command"); string name; sp.get_string("name", name); @@ -1104,6 +1104,21 @@ void Container_manager::exec(string command) if (*j == '\\') i->erase(j); + string env; + sp.get_string("env", env); + + if (env[0] == '\'') /* Strip ' from both ends. */ + env = env.substr(1, env.size() - 2); + + vector envs; + split(env, ' ', envs); + + /* Remove a single layer of backslashes. */ + for (vector::iterator i = envs.begin(); i != envs.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(); @@ -1111,7 +1126,7 @@ void Container_manager::exec(string command) std::ostringstream ss; ss << "About to execute"; - /* We use global allocators so that _exec_argv survives after + /* We use global allocators so that _exec_* survive after the container manager is destroyed. */ _exec_argv = new char*[argvs.size() + 1]; for (int i = 0; i < argvs.size(); i++) @@ -1122,5 +1137,15 @@ void Container_manager::exec(string command) } _exec_argv[argvs.size()] = NULL; + ss << " [environment]"; + _exec_env = new char*[envs.size() + 1]; + for (int i = 0; i < envs.size(); i++) + { + _exec_env[i] = new char[envs[i].size() + 1]; + strcpy(_exec_env[i], envs[i].c_str()); + ss << " '" << envs[i] << "'"; + } + _exec_env[envs.size()] = NULL; + _logger->log(LOG_TYPE_INFO, ss.str()); } diff --git a/src/container_manager.hpp b/src/container_manager.hpp index a33a34c..c62cc35 100644 --- a/src/container_manager.hpp +++ b/src/container_manager.hpp @@ -34,6 +34,7 @@ class Container_manager string _argo_argo_containers_root; char ** _exec_argv; + char ** _exec_env; Container_manager(Container_manager& orig) = delete; Container_manager& operator = (const Container_manager& orig) = delete; @@ -235,6 +236,7 @@ class Container_manager 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;} + inline char** get_exec_env() const {return _exec_env;} void show_available_resources(string command); void create_container(string command); -- 2.26.2