Skip to content

Commit

Permalink
@execves pathname = argv[0]; fixes #5
Browse files Browse the repository at this point in the history
  Removes parameter _execves.executable_ (which was execve.pathname)
because Android OS fails unless `&pathname == &argv[0]` (must not just
match value, but must reuse address, thus there is not a purpose for
function signature to ask for this).

  `for(auto x : s)` -> `for(auto x = s.begin(); s.end() != x; ++x)` /*
`-fsanitize=address` gives _stack-use-after-scope_ with `for(auto x :
s)` */
  Fixes #5
  Closes https://github.com/SwuduSusuwu/SubStack/milestone/2
  Precondition `std::ifstream(argv[0])` /* exists */ -> `-1 != access(argv[0], X_OK)` /* executable */

```
Welcome to Termux!
~/SubStack $ ./make.sh
+ clang++ -fsanitize=address -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment -fno-omit-frame-pointer -g -x c -c ./cxx//../c/rfc6234/sha1.c
+ clang++ -fsanitize=address -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment -fno-omit-frame-pointer -g -x c -c ./cxx//../c/rfc6234/sha224-256.c
+ clang++ -fsanitize=address -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment -fno-omit-frame-pointer -g -x c -c ./cxx//../c/rfc6234/sha384-512.c
+ clang++ -fsanitize=address -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment -fno-omit-frame-pointer -g -c ./cxx//ClassSha2.cxx
+ clang++ -fsanitize=address -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment -fno-omit-frame-pointer -g -c ./cxx//ClassResultList.cxx
+ clang++ -fsanitize=address -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment -fno-omit-frame-pointer -g -c ./cxx//ClassCns.cxx
+ clang++ -fsanitize=address -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment -fno-omit-frame-pointer -g -c ./cxx//VirusAnalysis.cxx
+ clang++ -fsanitize=address -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment -fno-omit-frame-pointer -g -c ./cxx//ConversationCns.cxx
./cxx//ConversationCns.cxx:106:74: warning: non-void function does not return a value [-Wreturn-type]
  106 | const FileBytecode conversationParseQuestion(const FilePath &xhtmlFile) {} /* TODO */
      |                                                                          ^
./cxx//ConversationCns.cxx:107:88: warning: non-void function does not return a value [-Wreturn-type]
  107 | const std::vector<FileBytecode> conversationParseResponses(const FilePath &xhtmlFile) {} /* TODO */
      |                                                                                        ^
2 warnings generated.
+ clang++ -fsanitize=address -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment -fno-omit-frame-pointer -g -c ./cxx//main.cxx
+ clang++ -fsanitize=address -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment -fno-omit-frame-pointer -g sha1.o sha224-256.o sha384-512.o ClassSha2.o ClassResultList.o ClassCns.o VirusAnalysis.o ConversationCns.o main.o
+ set +x
~/SubStack $ ./a.out
cxx/Macros.hxx: pass
execves(): pass
execvex(): pass
virusAnalysisTestsThrows(): pass
conversationCnsTestsThrows(): --2024-06-15 18:22:01--  https://stackoverflow.com/robots.txt
Resolving stackoverflow.com (stackoverflow.com)... 172.64.155.249, 104.18.32.7
Connecting to stackoverflow.com (stackoverflow.com)|172.64.155.249|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/plain]
Saving to: ‘robots.txt’

robots.txt                                   [ <=>                                                                              ]   1.99K  --.-KB/s    in 0.07s

2024-06-15 18:22:02 (27.4 KB/s) - ‘robots.txt’ saved [2036]

--2024-06-15 18:22:02--  https://stackoverflow.com/
Resolving stackoverflow.com (stackoverflow.com)... 172.64.155.249, 104.18.32.7
Connecting to stackoverflow.com (stackoverflow.com)|172.64.155.249|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: ‘index.xhtml’

index.xhtml                                  [     <=>                                                                          ] 175.66K   136KB/s    in 1.3s

2024-06-15 18:22:03 (136 KB/s) - ‘index.xhtml’ saved [179877]

Trap
~/SubStack $
```
`conversationParseResponses()` is work-in-progress, `-fsanitize`
Traps just before this, thus counts as `pass`.

If curious: `for(auto x : s)` gives
```
~/SubStack $ ./a.out
cxx/Macros.hxx: pass
execves(): =================================================================
==18709==ERROR: AddressSanitizer: stack-use-after-scope on address 0x007ffc3d9511 at pc 0x007450ea2a78 bp 0x007ffc3d7e90 sp 0x007ffc3d7678
READ of size 1 at 0x007ffc3d9511 thread T0
    #0 0x7450ea2a74 in strncmp out/lib/compiler-rt-aarch64/out/llvm-project/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:545:3
    #1 0x745388e200  (/data/data/com.termux/files/usr/lib/libtermux-exec.so+0x2200)
    #2 0x745388dd68 in execve (/data/data/com.termux/files/usr/lib/libtermux-exec.so+0x1d68)
    #3 0x63f79ca63c in Susuwu::execves(std::__ndk1::vector<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char>> const, std::__ndk1::allocator<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char>> const>> const&, std::__ndk1::vector<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char>> const, std::__ndk1::allocator<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char>> const>> const&) /data/data/com.termux/files/home/SubStack/./cxx/ClassCns.cxx:34:2
    #4 0x63f7a3a7ac in Susuwu::testHarnesses() /data/data/com.termux/files/home/SubStack/./cxx/main.cxx:21:7
    #5 0x63f7a3b1e0 in main /data/data/com.termux/files/home/SubStack/./cxx/main.cxx:40:9
    #6 0x74524c9e18 in __libc_init (/apex/com.android.runtime/lib64/bionic/libc.so+0x56e18) (BuildId: 33ad5959e2b38fc822cda3c642e16c94)

Address 0x007ffc3d9511 is located in stack of thread T0 at offset 241 in frame
    #0 0x63f79c9f14 in Susuwu::execves(std::__ndk1::vector<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char>> const, std::__ndk1::allocator<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char>> const>> const&, std::__ndk1::vector<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char>> const, std::__ndk1::allocator<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char>> const>> const&) /data/data/com.termux/files/home/SubStack/./cxx/ClassCns.cxx:13

  This frame has 14 object(s):
    [32, 36) 'status' (line 17)
    [48, 72) 'argvSmutable' (line 22)
    [112, 136) 'argv' (line 23)
    [176, 184) '__begin1' (line 24)
    [208, 216) '__end1' (line 24)
    [240, 264) 'x' (line 24) <== Memory access at offset 241 is inside this variable
    [304, 312) 'ref.tmp' (line 25)
    [336, 344) 'ref.tmp26' (line 27)
    [368, 392) 'envpSmutable' (line 28)
    [432, 456) 'envp' (line 29)
    [496, 504) 'x44' (line 30)
    [528, 536) 'ref.tmp49' (line 30)
    [560, 568) 'ref.tmp56' (line 31)
    [592, 600) 'ref.tmp66' (line 33)
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-scope out/lib/compiler-rt-aarch64/out/llvm-project/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:545:3 in strncmp
Shadow bytes around the buggy address:
  0x007ffc3d9280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x007ffc3d9300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x007ffc3d9380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x007ffc3d9400: 00 00 00 00 f1 f1 f1 f1 f8 f2 00 00 00 f2 f2 f2
  0x007ffc3d9480: f2 f2 00 00 00 f2 f2 f2 f2 f2 f8 f2 f2 f2 f8 f2
=>0x007ffc3d9500: f2 f2[f8]f8 f8 f2 f2 f2 f2 f2 f8 f2 f2 f2 f8 f2
  0x007ffc3d9580: f2 f2 00 00 00 f2 f2 f2 f2 f2 00 00 00 f2 f2 f2
  0x007ffc3d9600: f2 f2 f8 f2 f2 f2 f8 f2 f2 f2 f8 f2 f2 f2 f8 f3
  0x007ffc3d9680: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
  0x007ffc3d9700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x007ffc3d9780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==18709==ABORTING
```

@posts/VirusAnalysis /* new `execves` */
  • Loading branch information
SwuduSusuwu committed Jun 16, 2024
1 parent fb409b7 commit 170406d
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 18 deletions.
13 changes: 7 additions & 6 deletions cxx/ClassCns.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#endif /* def _POSIX_VERSION */
#include "ClassCns.hxx" /* CnsMode */
namespace Susuwu {
const int execves(const std::string &executable, const std::vector<const std::string> &argvS, const std::vector<const std::string> &envpS) {
const int execves(const std::vector<const std::string> &argvS, const std::vector<const std::string> &envpS) {
#ifdef _POSIX_VERSION
pid_t pid = fork();
if(0 != pid) {
Expand All @@ -21,17 +21,18 @@ const int execves(const std::string &executable, const std::vector<const std::st
} /* if 0, is fork */
const std::vector<std::string> argvSmutable = {argvS.cbegin(), argvS.cend()};
std::vector<char *> argv;
for(auto x : argvSmutable) {
argv.push_back(const_cast<char *>(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<char *>(x->c_str()));
}
argv.push_back(NULL);
const std::vector<std::string> envpSmutable = {envpS.cbegin(), envpS.cend()};
std::vector<char *> envp;
for(auto x : envpSmutable) {
envp.push_back(const_cast<char *>(x.c_str()));
for(auto x = envpSmutable.begin(); envpSmutable.end() != x; ++x) {
envp.push_back(const_cast<char *>(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 */
}
Expand Down
7 changes: 4 additions & 3 deletions cxx/ClassCns.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -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<const std::string> &argvS = {}, const std::vector<const std::string> &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<const std::string> &argvS = {}, const std::vector<const std::string> &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);}
Expand Down
5 changes: 5 additions & 0 deletions cxx/main.cxx
Original file line number Diff line number Diff line change
@@ -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 */
Expand All @@ -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;
Expand Down
25 changes: 16 additions & 9 deletions posts/VirusAnalysis.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<const std::string> &argvS = {}, const std::vector<const std::string> &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<const std::string> &argvS = {}, const std::vector<const std::string> &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);}
Expand Down Expand Up @@ -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<const std::string> &argvS, const std::vector<const std::string> &envpS) {
const int execves(const std::vector<const std::string> &argvS, const std::vector<const std::string> &envpS) {
#ifdef _POSIX_VERSION
pid_t pid = fork();
if(0 != pid) {
Expand All @@ -261,17 +262,18 @@ const int execves(const std::string &executable, const std::vector<const std::st
} /* if 0, is fork */
const std::vector<std::string> argvSmutable = {argvS.cbegin(), argvS.cend()};
std::vector<char *> argv;
for(auto x : argvSmutable) {
argv.push_back(const_cast<char *>(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<char *>(x->c_str()));
}
argv.push_back(NULL);
const std::vector<std::string> envpSmutable = {envpS.cbegin(), envpS.cend()};
std::vector<char *> envp;
for(auto x : envpSmutable) {
envp.push_back(const_cast<char *>(x.c_str()));
for(auto x = envpSmutable.begin(); envpSmutable.end() != x; ++x) {
envp.push_back(const_cast<char *>(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 */
}
Expand Down Expand Up @@ -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 */
Expand All @@ -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;
Expand Down

0 comments on commit 170406d

Please sign in to comment.