nus-apr / CrashRepair

Security Vulnerability Repair via Concolic Execution and Code Mutations
17 stars 1 forks source link

Correct patch produces erroneous exit code when compiled with -fsanitize=address #125

Closed rshariffdeen closed 1 year ago

rshariffdeen commented 1 year ago

While investigating why no plausible patches for gnubug-25003 in coreutils I observed that validation incorrectly removes a correct patch which states that observed exit code is 1 However if I manually apply the patch and run the exploit it exit with code 0

2023-03-27 05:43:30.960 | INFO     | crashrepair.scenario:evaluate:489 - candidate #5 fails test #crash
2023-03-27 05:43:30.966 | INFO     | crashrepair.scenario:evaluate:464 - evaluating candidate patch #6:
@@ -982,7 +982,7 @@
   start = (k - 1) * (file_size / n);
   end = (k == n) ? file_size : k * (file_size / n);

-  if (initial_read != SIZE_MAX || start < initial_read)
+  if ((((start < initial_read) && (start < (initial_read - start)))) && (initial_read != SIZE_MAX || start < initial_read))
     {
       memmove (buf, buf + start, initial_read - start);
       initial_read -= start;

2023-03-27 05:43:30.971 | DEBUG    | crashrepair.scenario:rebuild:339 - using environment: {'CC': '/opt/llvm11/bin/clang', 'CXX': '/opt/llvm11/bin/clang++', 'CFLAGS': '-g -O0 -Wno-error -L/klee/build/lib -lkleeRuntest -I/CrashRepair/lib -L/CrashRepair/lib -lcrepair_runtime -lcrepair_proxy -fsanitize=address', 'CXXFLAGS': '-g -O0 -Wno-error -L/klee/build/lib -lkleeRuntest -I/CrashRepair/lib -L/CrashRepair/lib -lcrepair_runtime -lcrepair_proxy -fsanitize=address', 'LDFLAGS': '-g -O0 -Wno-error -L/klee/build/lib -lkleeRuntest -I/CrashRepair/lib -L/CrashRepair/lib -lcrepair_runtime -lcrepair_proxy -fsanitize=address', 'INJECT_CFLAGS': '-g -O0 -Wno-error -L/klee/build/lib -lkleeRuntest -I/CrashRepair/lib -L/CrashRepair/lib -lcrepair_runtime -lcrepair_proxy -fsanitize=address', 'INJECT_CXXFLAGS': '-g -O0 -Wno-error -L/klee/build/lib -lkleeRuntest -I/CrashRepair/lib -L/CrashRepair/lib -lcrepair_runtime -lcrepair_proxy -fsanitize=address', 'INJECT_LDFLAGS': '-g -O0 -Wno-error -L/klee/build/lib -lkleeRuntest -I/CrashRepair/lib -L/CrashRepair/lib -lcrepair_runtime -lcrepair_proxy -fsanitize=address'}
2023-03-27 05:43:30.972 | DEBUG    | crashrepair.shell:__call__:38 - executing: make CFLAGS="-ggdb -fPIC -fPIE ${INJECT_CFLAGS:-}" CXXFLAGS="-ggdb -fPIC -fPIE ${INJECT_CXXFLAGS:-}" LDFLAGS="${INJECT_LDFLAGS:-}" src/split
  CC       src/split.o
clang-6.0: warning: -lkleeRuntest: 'linker' input unused [-Wunused-command-line-argument]
clang-6.0: warning: -lcrepair_runtime: 'linker' input unused [-Wunused-command-line-argument]
clang-6.0: warning: -lcrepair_proxy: 'linker' input unused [-Wunused-command-line-argument]
clang-6.0: warning: -lcrepair_runtime: 'linker' input unused [-Wunused-command-line-argument]
clang-6.0: warning: -lcrepair_proxy: 'linker' input unused [-Wunused-command-line-argument]
clang-6.0: warning: -lkleeRuntest: 'linker' input unused [-Wunused-command-line-argument]
clang-6.0: warning: argument unused during compilation: '-L/klee/build/lib' [-Wunused-command-line-argument]
clang-6.0: warning: argument unused during compilation: '-L/CrashRepair/lib' [-Wunused-command-line-argument]
clang-6.0: warning: argument unused during compilation: '-L/CrashRepair/compiler/../lib/' [-Wunused-command-line-argument]
clang-6.0: warning: argument unused during compilation: '-L/klee/build/lib/' [-Wunused-command-line-argument]
  CCLD     src/split
2023-03-27 05:43:32.623 | DEBUG    | crashrepair.scenario:evaluate:484 - testing candidate #6 against test #crash...
2023-03-27 05:43:32.624 | DEBUG    | crashrepair.shell:__call__:38 - executing: /data/vulnloc/coreutils/gnubug-25003/src/src/split -n7/75 /dev/null
2023-03-27 05:43:33.382 | DEBUG    | crashrepair.test:run:47 - test output [stdout]: 
2023-03-27 05:43:33.383 | DEBUG    | crashrepair.test:run:48 - test output [stderr]: 
2023-03-27 05:43:33.383 | DEBUG    | crashrepair.test:run:58 - test failed: unexpected exit code (actual: 1, expected: 0)
ChrisTimperley commented 1 year ago

TL;DR: it's the compilation settings, again.

I'm able to reproduce this behavior. I see that during patch validation, the believed exit code is 1, and, like you, when I apply those changes and recompile manually, the exit code is 0.

Edit: The exit code seems to depend on the compilation flags that I use. If I use those used by the patch validation, I also get an exit code 1:

root@03140f4b53cf:/data/vulnloc/coreutils/gnubug-25003/src# make CFLAGS="-ggdb -fPIC -fPIE ${INJECT_CFLAGS}" CXXFLAGS="-ggdb -fPIC -fPIE ${INJECT_CXXFLAGS}" LDFLAGS="${INJECT_LDFLAGS}" src/split
  CC       src/split.o
clang-6.0: warning: -lkleeRuntest: 'linker' input unused [-Wunused-command-line-argument]
clang-6.0: warning: -lcrepair_runtime: 'linker' input unused [-Wunused-command-line-argument]
clang-6.0: warning: -lcrepair_proxy: 'linker' input unused [-Wunused-command-line-argument]
clang-6.0: warning: -lcrepair_runtime: 'linker' input unused [-Wunused-command-line-argument]
clang-6.0: warning: -lcrepair_proxy: 'linker' input unused [-Wunused-command-line-argument]
clang-6.0: warning: -lkleeRuntest: 'linker' input unused [-Wunused-command-line-argument]
clang-6.0: warning: argument unused during compilation: '-L/klee/build/lib' [-Wunused-command-line-argument]
clang-6.0: warning: argument unused during compilation: '-L/CrashRepair/lib' [-Wunused-command-line-argument]
clang-6.0: warning: argument unused during compilation: '-L/CrashRepair/compiler/../lib/' [-Wunused-command-line-argument]
clang-6.0: warning: argument unused during compilation: '-L/klee/build/lib/' [-Wunused-command-line-argument]
  CCLD     src/split
root@03140f4b53cf:/data/vulnloc/coreutils/gnubug-25003/src# cd ../
root@03140f4b53cf:/data/vulnloc/coreutils/gnubug-25003# /data/vulnloc/coreutils/gnubug-25003/src/src/split -n7/75 /dev/null; echo $?
hello world!
1

If I don't inject those CFLAGS/CXXFLAGS/LDFLAGS, I get an exit code of 0:

root@03140f4b53cf:/data/vulnloc/coreutils/gnubug-25003/src# make
make  all-recursive
make[1]: Entering directory '/data/vulnloc/coreutils/gnubug-25003/src'
Making all in po
make[2]: Entering directory '/data/vulnloc/coreutils/gnubug-25003/src/po'
make[2]: Nothing to be done for 'all'.
make[2]: Leaving directory '/data/vulnloc/coreutils/gnubug-25003/src/po'
Making all in .
make[2]: Entering directory '/data/vulnloc/coreutils/gnubug-25003/src'
  CC       src/split.o
clang-6.0: warning: -lcrepair_runtime: 'linker' input unused [-Wunused-command-line-argument]
clang-6.0: warning: -lcrepair_proxy: 'linker' input unused [-Wunused-command-line-argument]
clang-6.0: warning: -lkleeRuntest: 'linker' input unused [-Wunused-command-line-argument]
clang-6.0: warning: argument unused during compilation: '-L/CrashRepair/compiler/../lib/' [-Wunused-command-line-argument]
clang-6.0: warning: argument unused during compilation: '-L/klee/build/lib/' [-Wunused-command-line-argument]
  CCLD     src/split
  GEN      man/split.1
make[2]: Leaving directory '/data/vulnloc/coreutils/gnubug-25003/src'
Making all in gnulib-tests
make[2]: Entering directory '/data/vulnloc/coreutils/gnubug-25003/src/gnulib-tests'
make  all-recursive
make[3]: Entering directory '/data/vulnloc/coreutils/gnubug-25003/src/gnulib-tests'
Making all in .
make[4]: Entering directory '/data/vulnloc/coreutils/gnubug-25003/src/gnulib-tests'
make[4]: Nothing to be done for 'all-am'.
make[4]: Leaving directory '/data/vulnloc/coreutils/gnubug-25003/src/gnulib-tests'
make[3]: Leaving directory '/data/vulnloc/coreutils/gnubug-25003/src/gnulib-tests'
make[2]: Leaving directory '/data/vulnloc/coreutils/gnubug-25003/src/gnulib-tests'
make[1]: Leaving directory '/data/vulnloc/coreutils/gnubug-25003/src'
root@03140f4b53cf:/data/vulnloc/coreutils/gnubug-25003/src# /data/vulnloc/coreutils/gnubug-25003/src/src/split -n7/75 /dev/null; echo $?
hello worldz!
0

As soon as I no longer compile with -fsanitize=address (but otherwise retain all of the other options), the exit code goes to 0. So, for some weird reason, -fsanitize=address is causing the program to produce an exit code of 1 without printing any kind of error message.

ChrisTimperley commented 1 year ago

Alright, I got to the bottom of it. ASAN will, by default, produce an exit code of 1 if it detects any sort of memory leak (including false positives). Since we're not making any promises about fixing memory leaks, the simple fix is for the validation step to use detect_leaks=0 in ASAN_OPTIONS. I'll fix this up now.

Related: