diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b2dd1bfb693f81baee5d0f2bf47c82b8d27b5b10..549755dd7ce3d134411e2ad2f8da8a08ed88cf99 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -145,3 +145,66 @@ xform-cat-centos75: variables: OS: 'centos75' + +# +# CFI test_foo +# + +# template +.test_foo: &test_foo + stage: test + script: + - ./cicd_tests/test_foo.sh + +test_foo-ubuntu18: + <<: *test_foo + tags: + - ubuntu18 + variables: + OS: 'ubuntu18' + +test_foo-ubuntu16: + <<: *test_foo + tags: + - ubuntu16 + variables: + OS: 'ubuntu16' + +test_foo-centos75: + <<: *test_foo + tags: + - centos75 + variables: + OS: 'centos75' + + +# +# CFI test_fib +# + +# template +.test_fib: &test_fib + stage: test + script: + - ./cicd_tests/test_fib.sh + +test_fib-ubuntu18: + <<: *test_fib + tags: + - ubuntu18 + variables: + OS: 'ubuntu18' + +test_fib-ubuntu16: + <<: *test_fib + tags: + - ubuntu16 + variables: + OS: 'ubuntu16' + +test_fib-centos75: + <<: *test_fib + tags: + - centos75 + variables: + OS: 'centos75' diff --git a/cicd_tests/cfi_smokescreen_configs.sh b/cicd_tests/cfi_smokescreen_configs.sh new file mode 100644 index 0000000000000000000000000000000000000000..8b5d6d2e62ad04f6831db4193254b7b656f6e4f1 --- /dev/null +++ b/cicd_tests/cfi_smokescreen_configs.sh @@ -0,0 +1,64 @@ +#!/bin/bash + + +configs=(do_cfi_4_byte + do_coloring_cfi_4_byte + do_cfi_exe_nonces_1_byte + do_cfi_exe_nonces + do_cfi_exe_nonces_4_byte_non_exe_color_non_exe + do_cfi_exe_nonces_8_byte + do_cfi_exe_nonces_1_byte_color_exe + do_cfi_exe_nonces_color_exe + do_cfi_exe_nonces_8_byte_color_exe + do_cfi_exe_nonces_4_byte_non_exe_color_both) + + +do_cfi_4_byte() +{ + $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only --step-option fix_calls:--fix-all --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 4" +} + +do_coloring_cfi_4_byte() +{ + $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only --step-option fix_calls:--fix-all --step-option selective_cfi:--color --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 4" +} + +do_cfi_exe_nonces_1_byte() +{ + $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 1" +} + +do_cfi_exe_nonces() +{ + $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" +} + +do_cfi_exe_nonces_4_byte_non_exe_color_non_exe() +{ + $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 4" --step-option selective_cfi:--color +} + +do_cfi_exe_nonces_8_byte() +{ + $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 8" +} + +do_cfi_exe_nonces_1_byte_color_exe() +{ + $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 1" --step-option selective_cfi:--color-exe-nonces +} + +do_cfi_exe_nonces_color_exe() +{ + $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:--color-exe-nonces +} + +do_cfi_exe_nonces_8_byte_color_exe() +{ + $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 8" --step-option selective_cfi:--color-exe-nonces +} + +do_cfi_exe_nonces_4_byte_non_exe_color_both() +{ + $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 4" --step-option selective_cfi:--color-exe-nonces --step-option selective_cfi:--color +} diff --git a/cicd_tests/fib.c b/cicd_tests/fib.c new file mode 100644 index 0000000000000000000000000000000000000000..15a198c0357b09b441e6aaed25c688602159e813 --- /dev/null +++ b/cicd_tests/fib.c @@ -0,0 +1,53 @@ +#include <stdio.h> + +extern int fib(); +extern int fib2(); +extern int fibp(int n, int (*)(int,int)); + +int add(int n1, int n2) +{ + if (n1 == 0) + return n2; + else if (n2 == 0) + return n1; + else if (n1 == 2) + return add(1, add(1, n2)); + else + return n1 + add(0, n2); +} + +main(int argc, char **argv) +{ + int x = 3; + int f = 0; + if (argc >= 2) + x = atoi(argv[1]); + + if (x <= 2) + f = fib_main(x); + if (x == 3) + f = fib2(x); + else if (x == 4) + f = fib_simple(x); + else if (x == 5) + f = fibp(x, &add); + else + f = fib(x); + printf("Fibonacci(%d) = %d\n", x, f); + + return f; +} + +fib_main(int f) { + if (f <= 2) + return 1; + else + return fib_simple(f-1) + fib_main(f-2); +} + +fib_simple(int f) { + if (f <= 2) + return 1; + else + return fib_simple(f-1) + fib_simple(f-2); +} diff --git a/cicd_tests/foo.c b/cicd_tests/foo.c new file mode 100644 index 0000000000000000000000000000000000000000..d0c95ea862c2dd32b49bbb4222edb92895a94ad7 --- /dev/null +++ b/cicd_tests/foo.c @@ -0,0 +1,14 @@ +#include <stdlib.h> +#include <stdio.h> + +extern int foo(); + +int main() +{ + foo(); +} + +int foo2() +{ + printf("In foo2\n"); +} diff --git a/cicd_tests/libfib.c b/cicd_tests/libfib.c new file mode 100644 index 0000000000000000000000000000000000000000..75fbd864e2932e215a2c7fd8b04868ee10d19081 --- /dev/null +++ b/cicd_tests/libfib.c @@ -0,0 +1,32 @@ +extern int fib_main(); +extern int fib2(); +extern int fib2p(int n, int (*)(int,int)); + +int add2(int n1, int n2) +{ + if (n1 == 0) + return n2; + else if (n2 == 0) + return n1; + else if (n2 == 2) + return add2(add2(n1, 1),1); + else + return add2(0, n2) + add2(n1, 0); +} + +int fib(int n) +{ + if (n <= 2) + return 1; + else + return fib_main(n-1) + fib2(n-2); + +} + +int fibp(int n, int (*addp)(int,int)) +{ + if (n <= 2) + return 1; + else + return (*addp)(fib_main(n-1),fib2p(n-2,&add2)); +} diff --git a/cicd_tests/libfib2.c b/cicd_tests/libfib2.c new file mode 100644 index 0000000000000000000000000000000000000000..c6438352234474e9cf44a53e62c47492b0e85f43 --- /dev/null +++ b/cicd_tests/libfib2.c @@ -0,0 +1,18 @@ +extern int fib_main(); +extern int fib(); + +int fib2(int n) +{ + if (n <= 2) + return 1; + else + return fib2(n-1) + fib_main(n-2); +} + +int fib2p(int n, int (*addp)(int,int)) +{ + if (n <= 2) + return (*addp)(1,0); + else + return (*addp)(fib2(n-1),fib2p(n-2, addp)); +} diff --git a/cicd_tests/libfoo.c b/cicd_tests/libfoo.c new file mode 100644 index 0000000000000000000000000000000000000000..2d83d2ef290376609c03b157b51770f2f0e226bb --- /dev/null +++ b/cicd_tests/libfoo.c @@ -0,0 +1,14 @@ +#include <math.h> +#include <stdio.h> +#include <stdint.h> + +int bar() +{ + printf("in bar\n"); +} +int foo() +{ + printf("in foo\n"); + foo2(); +} + diff --git a/cicd_tests/test_fib.sh b/cicd_tests/test_fib.sh new file mode 100755 index 0000000000000000000000000000000000000000..cc7e371d6801b2f3f1f52219369abd377e795a5c --- /dev/null +++ b/cicd_tests/test_fib.sh @@ -0,0 +1,126 @@ +#!/bin/bash + +set -x +source cfi_smokescreen_configs.sh + +get_correct() +{ + cp libfib.so.orig libfib.so + cp libfib2.so.orig libfib2.so + ./fib.exe $1 > correct + echo $? >> correct +} + +test() +{ + n=$2 + + get_correct $n + + cp $3 libfib.so + cp $4 libfib2.so + ./$1 $n > out + echo $? >> out + + cmp out correct + if [ $? = 1 ]; then + fails=$(expr $fails + 1 ) + echo test failed $1 $2 $3 $4 | tee -a fib_test_log.txt + echo "=== out ===" + cat out + echo "======" + echo "exiting" + clean + exit 1 + else + passes=$(expr $passes + 1 ) + echo test passed. + fi +} + + +build() +{ + gcc -o libfib.so libfib.c -w -shared -fPIC + gcc -o libfib2.so libfib2.c -w -shared -fPIC + gcc -o fib.exe fib.c -w -L. -lfib -lfib2 + gcc -o fib.exe.pie fib.c -fPIC -fpie -pie -w -L. -lfib -lfib2 + mv libfib.so libfib.so.orig + mv libfib2.so libfib2.so.orig +} + + +protect() +{ + files=(libfib.so.orig libfib2.so.orig fib.exe fib.exe.pie) + + libfib_so_orig_varients=(libfib.so.orig) + libfib2_so_orig_varients=(libfib2.so.orig) + fib_exe_varients=(fib.exe) + fib_exe_pie_varients=(fib.exe.pie) + + for file in "${files[@]}"; do + for config in "${configs[@]}"; do + echo Protecting file "$file" with config "$config" | tee -a fib_protection_log.txt + "$config" ./"$file" ./"$file"".""$config" | tee -a fib_protection_log.txt + varient_array_name="$(echo "$file" | sed -e 's/\./_/g')""_varients" + declare -n varient_array="$varient_array_name" + varient_array+=("$file"".""$config") + done + done +} + +clean() +{ + rm out >> /dev/null + rm correct >> /dev/null + rm fib_protection_log.txt >> /dev/null + rm -Rf fib.exe* peasoup_exe* lib*.so* >> /dev/null + + for config in "${configs[@]}"; do + rm *."$config" >> /dev/null + done +} + +report () +{ + total=$(expr $passes + $fails) + echo "Passes: $passes / $total" | tee -a fib_test_log.txt + echo "Fails : $fails / $total" | tee -a fib_test_log.txt + + if grep -q "Warning " ./fib_protection_log.txt + then + echo PROTECTION WARNINGS DETECTED! + clean + exit 1 + else + echo ALL PROTECTIONS SUCCESSFUL + clean + exit 0 + fi +} + +main() +{ + build + protect + + fib_varients=("${fib_exe_varients[@]}" "${fib_exe_pie_varients[@]}") + + for fib_varient in "${fib_varients[@]}"; do + for libfib_varient in "${libfib_so_orig_varients[@]}"; do + for libfib2_varient in "${libfib2_so_orig_varients[@]}"; do + for i in {2...6}; do + test "$fib_varient" $i "$libfib_varient" "$libfib2_varient" + done + done + done + done + + report +} + +passes=0 +fails=0 + +main $* diff --git a/cicd_tests/test_foo.sh b/cicd_tests/test_foo.sh new file mode 100755 index 0000000000000000000000000000000000000000..bb7d9a9c128bd97d8ac32ebd8a28aaa56363f31b --- /dev/null +++ b/cicd_tests/test_foo.sh @@ -0,0 +1,125 @@ +#!/bin/bash + +set -x +source cfi_smokescreen_configs.sh + +get_correct() +{ + cp libfoo.so.orig libfoo.so + ./foo.exe > correct +} + +test() +{ + + cp $2 libfoo.so + ./$1 > out + + cmp out correct + if [ $? = 1 ]; then + fails=$(expr $fails + 1 ) + echo test "$1" "$2" failed | tee -a foo_test_log.txt + clean + exit 1 + else + passes=$(expr $passes + 1 ) + echo test passed. + fi +} + + +build() +{ + gcc -o libfoo.so libfoo.c -w -shared -fPIC + gcc -o foo.exe foo.c -w -L. -lfoo + mv libfoo.so libfoo.so.orig + + gcc -o libfoo.O.so libfoo.c -O -w -shared -fPIC + gcc -o libfoo.O2.so libfoo.c -O2 -w -shared -fPIC + gcc -o libfoo.O3.so libfoo.c -O3 -w -shared -fPIC + gcc -o libfoo.Os.so libfoo.c -Os -w -shared -fPIC + mv libfoo.O.so libfoo.O.so.orig + mv libfoo.O2.so libfoo.O2.so.orig + mv libfoo.O3.so libfoo.O3.so.orig + mv libfoo.Os.so libfoo.Os.so.orig +} + + +protect() +{ + files=(foo.exe libfoo.so.orig libfoo.O.so.orig libfoo.O2.so.orig libfoo.O3.so.orig libfoo.Os.so.orig) + + foo_exe_varients=(foo.exe) + libfoo_so_orig_varients=(libfoo.so.orig) + libfoo_O_so_orig_varients=(libfoo.O.so.orig) + libfoo_O2_so_orig_varients=(libfoo.O2.so.orig) + libfoo_O3_so_orig_varients=(libfoo.O3.so.orig) + libfoo_Os_so_orig_varients=(libfoo.Os.so.orig) + + for file in "${files[@]}"; do + for config in "${configs[@]}"; do + echo Protecting file "$file" with config "$config" | tee -a foo_protection_log.txt + "$config" ./"$file" ./"$file"".""$config" | tee -a foo_protection_log.txt + varient_array_name="$(echo "$file" | sed -e 's/\./_/g')""_varients" + declare -n varient_array="$varient_array_name" + varient_array+=("$file"".""$config") + done + done + +} + +clean() +{ + rm out >> /dev/null + rm correct >> /dev/null + rm -rf peasoup_executable_directory.* >> /dev/null + rm *.orig >> /dev/null + rm *.exe >> /dev/null + rm *.so >> /dev/null + + for config in "${configs[@]}"; do + rm *."$config" >> /dev/null + done +} + +report () +{ + total=$(expr $passes + $fails) + echo "Passes: $passes / $total" | tee -a foo_test_log.txt + echo "Fails : $fails / $total" | tee -a foo_test_log.txt + + if grep -q "Warning " ./foo_protection_log.txt + then + echo PROTECTION WARNINGS DETECTED! + clean + exit 1 + else + echo ALL PROTECTIONS SUCCESSFUL + clean + exit 0 + fi +} + +main() +{ + build + protect + get_correct + + libfoo_varients=("${libfoo_so_orig_varients[@]}" "${libfoo_O_so_orig_varients[@]}" "${libfoo_O2_so_orig_varients[@]}" + "${libfoo_O3_so_orig_varients[@]}" "${libfoo_Os_so_orig_varients[@]}") + + + for foo_varient in "${foo_exe_varients[@]}"; do + for libfoo_varient in "${libfoo_varients[@]}"; do + test "$foo_varient" "$libfoo_varient" + done + done + + report +} + +passes=0 +fails=0 + +main $*