diff --git a/cxx/ClassCns.cxx b/cxx/ClassCns.cxx index 7f6b180..fff52df 100644 --- a/cxx/ClassCns.cxx +++ b/cxx/ClassCns.cxx @@ -10,7 +10,7 @@ #endif /* def _POSIX_VERSION */ #include "ClassCns.hxx" /* CnsMode */ namespace Susuwu { -const int execves(const std::string &executable, const std::vector &argvS, const std::vector &envpS) { +const int execves(const std::vector &argvS, const std::vector &envpS) { #ifdef _POSIX_VERSION pid_t pid = fork(); if(0 != pid) { @@ -21,17 +21,18 @@ const int execves(const std::string &executable, const std::vector argvSmutable = {argvS.cbegin(), argvS.cend()}; std::vector argv; - for(auto x : argvSmutable) { - argv.push_back(const_cast(x.c_str())); + //for(auto x : argvSmutable) { /* with `fsanitize=address` this triggers "stack-use-after-scope" */ + for(auto x = argvSmutable.begin(); argvSmutable.end() != x; ++x) { + argv.push_back(const_cast(x->c_str())); } argv.push_back(NULL); const std::vector envpSmutable = {envpS.cbegin(), envpS.cend()}; std::vector envp; - for(auto x : envpSmutable) { - envp.push_back(const_cast(x.c_str())); + for(auto x = envpSmutable.begin(); envpSmutable.end() != x; ++x) { + envp.push_back(const_cast(x->c_str())); } envp.push_back(NULL); - execve(executable.c_str(), &argv[0], &envp[0]); /* NORETURN */ + execve(argv[0], &argv[0], &envp[0]); /* NORETURN */ exit(EXIT_FAILURE); #endif /* def _POSIX_VERSION */ } diff --git a/cxx/ClassCns.hxx b/cxx/ClassCns.hxx index 38312cc..38213db 100644 --- a/cxx/ClassCns.hxx +++ b/cxx/ClassCns.hxx @@ -20,9 +20,10 @@ typedef enum CnsMode { #endif /* def CXX_17 else */ } CnsMode; -/* @pre @code std::ifstream(executable); @endcode */ -const int execves(const std::string &executable, const std::vector &argvS = {}, const std::vector &envpS = {}); -static const int execvex(const std::string &toSh) {return execves("/bin/sh", {"/bin/sh", "-c", toSh});} +/* `int status; pid_t pid = fork() || execve(argv[0], &argv[0], &envp[0]); waitpid(pid, &status, 0); return status;` + * @pre @code (-1 != access(argv[0], X_OK) @endcode */ +const int execves(/* const std::string &pathname, -- `execve` requires `&pathname == &argv[0]` */ const std::vector &argvS = {}, const std::vector &envpS = {}); +static const int execvex(const std::string &toSh) {return execves({"/bin/sh", "-c", toSh});} typedef class Cns { public: virtual const bool hasImplementation() const {return typeid(Cns) != typeid(this);} diff --git a/cxx/main.cxx b/cxx/main.cxx index 6f229c2..591223c 100644 --- a/cxx/main.cxx +++ b/cxx/main.cxx @@ -1,6 +1,7 @@ /* Licenses: allows all uses ("Creative Commons"/"Apache 2") */ #ifndef INCLUDES_cxx_main_cxx #define INCLUDES_cxx_main_cxx +#include "ClassCns.hxx" /* execves execvex */ #include "VirusAnalysis.hxx" /* virusAnalysisTestsThrows */ #include "ConversationCns.hxx" /* conversationCnsTestsThrows */ #include "Macros.hxx" /* ASSUME EXPECTS ENSURES NOEXCEPT NORETURN */ @@ -16,6 +17,10 @@ int testHarnesses() EXPECTS(true) ENSURES(true) { ASSUME(true); noExcept(); std::cout << "pass" << std::endl; + std::cout << "execves(): " << std::flush; + 0 == execves({"/bin/echo", "pass"}) || std::cout << "error" << std::endl; + std::cout << "execvex(): " << std::flush; + 0 == execvex("/bin/echo pass") || std::cout << "error" << std::endl; std::cout << "virusAnalysisTestsThrows(): " << std::flush; if(virusAnalysisTestsThrows()) { std::cout << "pass" << std::endl; diff --git a/posts/VirusAnalysis.md b/posts/VirusAnalysis.md index af29b6e..0b67ba0 100644 --- a/posts/VirusAnalysis.md +++ b/posts/VirusAnalysis.md @@ -160,9 +160,10 @@ typedef enum CnsMode { #endif /* def CXX_17 else */ } CnsMode; -/* @pre @code std::ifstream(executable); @endcode */ -const int execves(const std::string &executable, const std::vector &argvS = {}, const std::vector &envpS = {}); -static const int execvex(const std::string &toSh) {return execves("/bin/sh", {"/bin/sh", "-c", toSh});} +/* `int status; pid_t pid = fork() || execve(argv[0], &argv[0], &envp[0]); waitpid(pid, &status, 0); return status;` + * @pre @code (-1 != access(argv[0], X_OK) @endcode */ +const int execves(/* const std::string &pathname, -- `execve` requires `&pathname == &argv[0]` */ const std::vector &argvS = {}, const std::vector &envpS = {}); +static const int execvex(const std::string &toSh) {return execves({"/bin/sh", "-c", toSh});} typedef class Cns { public: virtual const bool hasImplementation() const {return typeid(Cns) != typeid(this);} @@ -250,7 +251,7 @@ typedef class ApxrCns : Cns { ``` `less` [cxx/ClassCns.cxx](https://github.com/SwuduSusuwu/SubStack/blob/trunk/cxx/ClassCns.cxx) ``` -const int execves(const std::string &executable, const std::vector &argvS, const std::vector &envpS) { +const int execves(const std::vector &argvS, const std::vector &envpS) { #ifdef _POSIX_VERSION pid_t pid = fork(); if(0 != pid) { @@ -261,17 +262,18 @@ const int execves(const std::string &executable, const std::vector argvSmutable = {argvS.cbegin(), argvS.cend()}; std::vector argv; - for(auto x : argvSmutable) { - argv.push_back(const_cast(x.c_str())); + //for(auto x : argvSmutable) { /* with `fsanitize=address` this triggers "stack-use-after-scope" */ + for(auto x = argvSmutable.begin(); argvSmutable.end() != x; ++x) { + argv.push_back(const_cast(x->c_str())); } argv.push_back(NULL); const std::vector envpSmutable = {envpS.cbegin(), envpS.cend()}; std::vector envp; - for(auto x : envpSmutable) { - envp.push_back(const_cast(x.c_str())); + for(auto x = envpSmutable.begin(); envpSmutable.end() != x; ++x) { + envp.push_back(const_cast(x->c_str())); } envp.push_back(NULL); - execve(executable.c_str(), &argv[0], &envp[0]); /* NORETURN */ + execve(argv[0], &argv[0], &envp[0]); /* NORETURN */ exit(EXIT_FAILURE); #endif /* def _POSIX_VERSION */ } @@ -644,6 +646,7 @@ const FileBytecode cnsDisinfection(const PortableExecutable &file, const Cns &cn ``` `less` [cxx/main.cxx](https://github.com/SwuduSusuwu/SubStack/blob/trunk/cxx/main.cxx) ``` +#include "ClassCns.hxx" /* execves execvex */ #include "VirusAnalysis.hxx" /* virusAnalysisTestsThrows */ #include "ConversationCns.hxx" /* conversationCnsTestsThrows */ #include "Macros.hxx" /* ASSUME EXPECTS ENSURES NOEXCEPT NORETURN */ @@ -659,6 +662,10 @@ int testHarnesses() EXPECTS(true) ENSURES(true) { ASSUME(true); noExcept(); std::cout << "pass" << std::endl; + std::cout << "execves(): " << std::flush; + 0 == execves({"/bin/echo", "pass"}) || std::cout << "error" << std::endl; + std::cout << "execvex(): " << std::flush; + 0 == execvex("/bin/echo pass") || std::cout << "error" << std::endl; std::cout << "virusAnalysisTestsThrows(): " << std::flush; if(virusAnalysisTestsThrows()) { std::cout << "pass" << std::endl;