Module Name: src Committed By: kamil Date: Wed Apr 4 23:51:35 UTC 2018
Modified Files: src/distrib/sets/lists/tests: mi src/tests/usr.bin/cc: Makefile Added Files: src/tests/usr.bin/cc: t_asan_double_free.sh t_asan_global_buffer_overflow.sh t_asan_heap_overflow.sh t_asan_off_by_one.sh t_asan_uaf.sh Log Message: Add new ATF tests for Address Sanitzier (ASan) Add new C and C++ tests: - t_asan_double_free - t_asan_global_buffer_overflow - t_asan_heap_overflow - t_asan_off_by_one - t_asan_uaf Each tests checks: - regular build - 32-bit - PIC - PIE - profile These tests require paxctl(8) to disable ASLR in order to work in a predictable way. This is especially true for all !regular builds with additional compiler flags. There are no static variations of these tests as this mode is not supported in upstream ASan. Enable these tests on amd64 and i386. Patch submitted by <Siddharth Muralee> Additional polishing by myself. To generate a diff of this commit: cvs rdiff -u -r1.779 -r1.780 src/distrib/sets/lists/tests/mi cvs rdiff -u -r1.1 -r1.2 src/tests/usr.bin/cc/Makefile cvs rdiff -u -r0 -r1.1 src/tests/usr.bin/cc/t_asan_double_free.sh \ src/tests/usr.bin/cc/t_asan_global_buffer_overflow.sh \ src/tests/usr.bin/cc/t_asan_heap_overflow.sh \ src/tests/usr.bin/cc/t_asan_off_by_one.sh \ src/tests/usr.bin/cc/t_asan_uaf.sh Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/distrib/sets/lists/tests/mi diff -u src/distrib/sets/lists/tests/mi:1.779 src/distrib/sets/lists/tests/mi:1.780 --- src/distrib/sets/lists/tests/mi:1.779 Wed Apr 4 16:42:48 2018 +++ src/distrib/sets/lists/tests/mi Wed Apr 4 23:51:35 2018 @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.779 2018/04/04 16:42:48 kamil Exp $ +# $NetBSD: mi,v 1.780 2018/04/04 23:51:35 kamil Exp $ # # Note: don't delete entries from here - mark them as "obsolete" instead. # @@ -3635,6 +3635,11 @@ ./usr/tests/usr.bin/c++ tests-usr.bin-tests compattestfile,atf,cxx ./usr/tests/usr.bin/c++/Atffile tests-usr.bin-tests compattestfile,atf,cxx ./usr/tests/usr.bin/c++/Kyuafile tests-usr.bin-tests compattestfile,atf,kyua,cxx +./usr/tests/usr.bin/c++/t_asan_double_free tests-usr.bin-tests compattestfile,atf,cxx +./usr/tests/usr.bin/c++/t_asan_global_buffer_overflow tests-usr.bin-tests compattestfile,atf,cxx +./usr/tests/usr.bin/c++/t_asan_heap_overflow tests-usr.bin-tests compattestfile,atf,cxx +./usr/tests/usr.bin/c++/t_asan_off_by_one tests-usr.bin-tests compattestfile,atf,cxx +./usr/tests/usr.bin/c++/t_asan_uaf tests-usr.bin-tests compattestfile,atf,cxx ./usr/tests/usr.bin/c++/t_call_once tests-usr.bin-tests compattestfile,atf,cxx ./usr/tests/usr.bin/c++/t_call_once2 tests-usr.bin-tests compattestfile,atf,cxx ./usr/tests/usr.bin/c++/t_cxxruntime tests-usr.bin-tests compattestfile,atf,cxx @@ -3645,6 +3650,11 @@ ./usr/tests/usr.bin/cc/Atffile tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/cc/Kyuafile tests-usr.bin-tests compattestfile,atf,kyua ./usr/tests/usr.bin/cc/t_hello tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/cc/t_asan_double_free tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/cc/t_asan_global_buffer_overflow tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/cc/t_asan_heap_overflow tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/cc/t_asan_off_by_one tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/cc/t_asan_uaf tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/cmp tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/cmp/Atffile tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/cmp/Kyuafile tests-usr.bin-tests compattestfile,atf,kyua Index: src/tests/usr.bin/cc/Makefile diff -u src/tests/usr.bin/cc/Makefile:1.1 src/tests/usr.bin/cc/Makefile:1.2 --- src/tests/usr.bin/cc/Makefile:1.1 Sat Mar 17 17:15:29 2012 +++ src/tests/usr.bin/cc/Makefile Wed Apr 4 23:51:35 2018 @@ -1,9 +1,15 @@ -# $NetBSD: Makefile,v 1.1 2012/03/17 17:15:29 jruoho Exp $ +# $NetBSD: Makefile,v 1.2 2018/04/04 23:51:35 kamil Exp $ .include <bsd.own.mk> TESTSDIR= ${TESTSBASE}/usr.bin/cc -TESTS_SH= t_hello +TESTS_SH= # +TESTS_SH+= t_asan_double_free +TESTS_SH+= t_asan_global_buffer_overflow +TESTS_SH+= t_asan_heap_overflow +TESTS_SH+= t_asan_off_by_one +TESTS_SH+= t_asan_uaf +TESTS_SH+= t_hello .include <bsd.test.mk> Added files: Index: src/tests/usr.bin/cc/t_asan_double_free.sh diff -u /dev/null src/tests/usr.bin/cc/t_asan_double_free.sh:1.1 --- /dev/null Wed Apr 4 23:51:35 2018 +++ src/tests/usr.bin/cc/t_asan_double_free.sh Wed Apr 4 23:51:35 2018 @@ -0,0 +1,211 @@ +# $NetBSD: t_asan_double_free.sh,v 1.1 2018/04/04 23:51:35 kamil Exp $ +# +# Copyright (c) 2018 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Siddharth Muralee. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +SUPPORT='n' +test_target() { + if uname -m | grep -q "amd64"; then + SUPPORT='y' + fi + + if uname -m | grep -q "i386"; then + SUPPORT='y' + fi +} + +atf_test_case double_free +double_free_head() { + atf_set "descr" "compile and run \"Double Free example\"" + atf_set "require.progs" "cc paxctl" +} + +atf_test_case double_free_profile +double_free_profile_head() { + atf_set "descr" "compile and run \"Double Free example\" with profiling option" + atf_set "require.progs" "cc paxctl" +} + +atf_test_case double_free_pic +double_free_pic_head() { + atf_set "descr" "compile and run PIC \"Double Free example\"" + atf_set "require.progs" "cc paxctl" +} + +atf_test_case double_free_pie +double_free_pie_head() { + atf_set "descr" "compile and run position independent (PIE) \"Double Free example\"" + atf_set "require.progs" "cc paxctl" +} + +atf_test_case double_free32 +double_free32_head() { + atf_set "descr" "compile and run \"Double Free example\" for/in netbsd32 emulation" + atf_set "require.progs" "cc paxctl file diff cat" +} + +atf_test_case target_not_supported +target_not_supported_head() +{ + atf_set "descr" "Test forced skip" +} + +double_free_body() { + cat > test.c << EOF +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +void foo(int index) { char *x = (char*)malloc(10 * sizeof(char)); memset(x, 0, 10); free(x); free(x - index); } +int main(int argc, char **argv) { foo(argc - 1); printf("CHECK\n"); exit(0); } +EOF + cc -fsanitize=address -o test test.c + paxctl +a test + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"double-free" ./test +} + +double_free_profile_body() { + cat > test.c << EOF +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +void foo(int index) { char *x = (char*)malloc(10 * sizeof(char)); memset(x, 0, 10); free(x); free(x - index); } +int main(int argc, char **argv) { foo(argc - 1); printf("CHECK\n"); exit(0); } +EOF + cc -fsanitize=address -o test -pg test.c + paxctl +a test + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"double-free" ./test +} + +double_free_pic_body() { + cat > test.c << EOF +#include <stdlib.h> +#include <stdio.h> +#include <stdio.h> +int foo(int); +void main(int argc, char **argv) {foo(argc - 1); printf("CHECK\n"); exit(0);} +EOF + cat > pic.c << EOF +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +void foo(int index) { char *x = (char*)malloc(10 * sizeof(char)); memset(x, 0, 10); free(x); free(x - index); } +EOF + cc -fsanitize=address -fPIC -shared -o libtest.so pic.c + cc -o test test.c -fsanitize=address -L. -ltest + paxctl +a test + + export LD_LIBRARY_PATH=. + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"double-free" ./test +} + +double_free_pie_body() { + # check whether this arch supports -pice + if ! cc -pie -dM -E - < /dev/null 2>/dev/null >/dev/null; then + atf_set_skip "cc -pie not supported on this architecture" + fi + cat > test.c << EOF +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +void foo(int index) { char *x = (char*)malloc(10 * sizeof(char)); memset(x, 0, 10); free(x); free(x - index); } +int main(int argc, char **argv) { foo(argc - 1); printf("CHECK\n"); exit(0); } +EOF + cc -fsanitize=address -o test -fpie -pie test.c + paxctl +a test + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"double-free" ./test +} + +double_free32_body() { + # check whether this arch is 64bit + if ! cc -dM -E - < /dev/null | fgrep -q _LP64; then + atf_skip "this is not a 64 bit architecture" + fi + if ! cc -m32 -dM -E - < /dev/null 2>/dev/null > ./def32; then + atf_skip "cc -m32 not supported on this architecture" + else + if fgrep -q _LP64 ./def32; then + atf_fail "cc -m32 does not generate netbsd32 binaries" + fi +fi + + cat > test.c << EOF +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +void foo(int index) { char *x = (char*)malloc(10 * sizeof(char)); memset(x, 0, 10); free(x); free(x - index); } +int main(int argc, char **argv) { foo(argc - 1); printf("CHECK\n"); exit(0); } +EOF + cc -fsanitize=address -o df32 -m32 test.c + cc -fsanitize=address -o df64 test.c + file -b ./df32 > ./ftype32 + file -b ./df64 > ./ftype64 + if diff ./ftype32 ./ftype64 >/dev/null; then + atf_fail "generated binaries do not differ" + fi + echo "32bit binaries on this platform are:" + cat ./ftype32 + echo "While native (64bit) binaries are:" + cat ./ftype64 + paxctl +a df32 + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"double-free" ./df32 + +# and another test with profile 32bit binaries + cat > test.c << EOF +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +void foo(int index) { char *x = (char*)malloc(10 * sizeof(char)); memset(x, 0, 10); free(x); free(x - index); } +int main(int argc, char **argv) { foo(argc - 1); printf("CHECK\n"); exit(0); } +EOF + cc -fsanitize=address -o test -pg -m32 test.c + paxctl +a test + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"double-free" ./test +} + +target_not_supported_body() +{ + atf_skip "Target is not supported" +} + +atf_init_test_cases() +{ + test_target + test $SUPPORT = 'n' && { + atf_add_test_case target_not_supported + return 0 + } + + atf_add_test_case double_free + atf_add_test_case double_free_profile + atf_add_test_case double_free_pic + atf_add_test_case double_free_pie + atf_add_test_case double_free32 + # static option not supported + # -static and -fsanitize=address can't be used together for compilation + # (gcc version 5.4.0 and clang 7.1) tested on April 2nd 2018. +} Index: src/tests/usr.bin/cc/t_asan_global_buffer_overflow.sh diff -u /dev/null src/tests/usr.bin/cc/t_asan_global_buffer_overflow.sh:1.1 --- /dev/null Wed Apr 4 23:51:35 2018 +++ src/tests/usr.bin/cc/t_asan_global_buffer_overflow.sh Wed Apr 4 23:51:35 2018 @@ -0,0 +1,211 @@ +# $NetBSD: t_asan_global_buffer_overflow.sh,v 1.1 2018/04/04 23:51:35 kamil Exp $ +# +# Copyright (c) 2018 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Siddharth Muralee. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +SUPPORT='n' +test_target() { + if uname -m | grep -q "amd64"; then + SUPPORT='y' + fi + + if uname -m | grep -q "i386"; then + SUPPORT='y' + fi +} + +atf_test_case global_buffer_overflow +global_buffer_overflow_head() { + atf_set "descr" "compile and run \"Global Buffer Overflow example\"" + atf_set "require.progs" "cc paxctl" +} + +atf_test_case global_buffer_overflow_profile +global_buffer_overflow_profile_head() { + atf_set "descr" "compile and run \"Global Buffer Overflow example\" with profiling option" + atf_set "require.progs" "cc paxctl" +} + +atf_test_case global_buffer_overflow_pic +global_buffer_overflow_pic_head() { + atf_set "descr" "compile and run PIC \"Global Buffer Overflow example\"" + atf_set "require.progs" "cc paxctl" +} + +atf_test_case global_buffer_overflow_pie +global_buffer_overflow_pie_head() { + atf_set "descr" "compile and run position independent (PIE) \"Global Buffer Overflow example\"" + atf_set "require.progs" "cc paxctl" +} + +atf_test_case global_buffer_overflow32 +global_buffer_overflow32_head() { + atf_set "descr" "compile and run \"Global Buffer Overflow example\" for/in netbsd32 emulation" + atf_set "require.progs" "cc paxctl file diff cat" +} + +atf_test_case target_not_supported +target_not_supported_head() +{ + atf_set "descr" "Test forced skip" +} + +global_buffer_overflow_body() { + cat > test.c << EOF +#include <stdio.h> +#include <stdlib.h> +int arr[5] = {-1}; +void foo(int index) { arr[index] = 0; } +void main(int argc, char **argv) {foo(argc + 5); printf("CHECK\n"); exit(0);} +EOF + cc -fsanitize=address -o test test.c + paxctl -a test + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"global-buffer-overflow" ./test +} + +global_buffer_overflow_profile_body() { + cat > test.c << EOF +#include <stdio.h> +#include <stdlib.h> +int arr[5] = {-1}; +void foo(int index) { arr[index] = 0; } +void main(int argc, char **argv) {foo(argc + 5); printf("CHECK\n"); exit(0);} +EOF + cc -fsanitize=address -o test -pg test.c + paxctl +a test + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"global-buffer-overflow" ./test +} + +global_buffer_overflow_pic_body() { + cat > test.c << EOF +#include <stdio.h> +#include <stdlib.h> +void foo(int); +void main(int argc, char **argv) {foo(argc + 5); printf("CHECK\n"); exit(0);} +EOF + cat > pic.c << EOF +#include <stdio.h> +#include <stdlib.h> +int arr[5] = {-1}; +void foo(int index) { arr[index] = 0; } +EOF + + cc -fPIC -fsanitize=address -shared -o libtest.so pic.c + cc -o test test.c -fsanitize=address -L. -ltest + paxctl +a test + + export LD_LIBRARY_PATH=. + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"global-buffer-overflow" ./test +} + +global_buffer_overflow_pie_body() { + # check whether this arch supports -pice + if ! cc -pie -dM -E - < /dev/null 2>/dev/null >/dev/null; then + atf_set_skip "cc -pie not supported on this architecture" + fi + cat > test.c << EOF +#include <stdio.h> +#include <stdlib.h> +int arr[5] = {-1}; +void foo(int index) { arr[index] = 0; } +void main(int argc, char **argv) {foo(argc + 5); printf("CHECK\n"); exit(0);} +EOF + cc -fsanitize=address -fpie -pie -o test test.c + paxctl +a test + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"global-buffer-overflow" ./test +} + +global_buffer_overflow32_body() { + # check whether this arch is 64bit + if ! cc -dM -E - < /dev/null | fgrep -q _LP64; then + atf_skip "this is not a 64 bit architecture" + fi + if ! cc -m32 -dM -E - < /dev/null 2>/dev/null > ./def32; then + atf_skip "cc -m32 not supported on this architecture" + else + if fgrep -q _LP64 ./def32; then + atf_fail "cc -m32 does not generate netbsd32 binaries" + fi +fi + + cat > test.c << EOF +#include <stdio.h> +#include <stdlib.h> +int arr[5] = {-1}; +void foo(int index) { arr[index] = 0; } +void main(int argc, char **argv) {foo(argc + 5); printf("CHECK\n"); exit(0);} +EOF + cc -fsanitize=address -o gbof32 -m32 test.c + cc -fsanitize=address -o gbof64 test.c + file -b ./gbof32 > ./ftype32 + file -b ./gbof64 > ./ftype64 + if diff ./ftype32 ./ftype64 >/dev/null; then + atf_fail "generated binaries do not differ" + fi + echo "32bit binaries on this platform are:" + cat ./ftype32 + echo "While native (64bit) binaries are:" + cat ./ftype64 + paxctl +a gbof32 + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"global-buffer-overflow" ./gbof32 + +# and another test with profile 32bit binaries + cat > test.c << EOF +#include <stdio.h> +#include <stdlib.h> +int arr[5] = {-1}; +void foo(int index) { arr[index] = 0; } +void main(int argc, char **argv) {foo(argc + 5); printf("CHECK\n"); exit(0);} +EOF + cc -o test -m32 -fsanitize=address -pg test.c + paxctl +a test + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"global-buffer-overflow" ./test +} + +target_not_supported_body() +{ + atf_skip "Target is not supported" +} + +atf_init_test_cases() +{ + test_target + test $SUPPORT = 'n' && { + atf_add_test_case target_not_supported + return 0 + } + + atf_add_test_case global_buffer_overflow + atf_add_test_case global_buffer_overflow_profile + atf_add_test_case global_buffer_overflow_pic + atf_add_test_case global_buffer_overflow_pie + atf_add_test_case global_buffer_overflow32 + # static option not supported + # -static and -fsanitize=address can't be used together for compilation + # (gcc version 5.4.0 and clang 7.1) tested on April 2nd 2018. +} Index: src/tests/usr.bin/cc/t_asan_heap_overflow.sh diff -u /dev/null src/tests/usr.bin/cc/t_asan_heap_overflow.sh:1.1 --- /dev/null Wed Apr 4 23:51:35 2018 +++ src/tests/usr.bin/cc/t_asan_heap_overflow.sh Wed Apr 4 23:51:35 2018 @@ -0,0 +1,212 @@ +# $NetBSD: t_asan_heap_overflow.sh,v 1.1 2018/04/04 23:51:35 kamil Exp $ +# +# Copyright (c) 2018 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Siddharth Muralee. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +SUPPORT='n' +test_target() { + if uname -m | grep -q "amd64"; then + SUPPORT='y' + fi + + if uname -m | grep -q "i386"; then + SUPPORT='y' + fi +} + +atf_test_case heap_overflow +heap_overflow_head() { + atf_set "descr" "compile and run \"Heap Overflow example\"" + atf_set "require.progs" "cc paxctl" +} + +atf_test_case heap_overflow_profile +heap_overflow_profile_head() { + atf_set "descr" "compile and run \"Heap Overflow example\" with profiling option" + atf_set "require.progs" "cc paxctl" +} + +atf_test_case heap_overflow_pic +heap_overflow_pic_head() { + atf_set "descr" "compile and run PIC \"Heap Overflow example\"" + atf_set "require.progs" "cc paxctl" +} + +atf_test_case heap_overflow_pie +heap_overflow_pie_head() { + atf_set "descr" "compile and run position independent (PIE) \"Heap Overflow example\"" + atf_set "require.progs" "cc paxctl" +} + +atf_test_case heap_overflow32 +heap_overflow32_head() { + atf_set "descr" "compile and run \"Heap Overflow example\" for/in netbsd32 emulation" + atf_set "require.progs" "cc paxctl file diff cat" +} + +atf_test_case target_not_supported +target_not_supported_head() +{ + atf_set "descr" "Test forced skip" +} + +heap_overflow_body() { + cat > test.c << EOF +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +int foo(int index) { int *x = (int *)malloc(20); int res = x[index * 4]; free(x); return res;} +int main(int argc, char **argv) {foo(argc + 19); printf("CHECK\n"); exit(0);} +EOF + cc -fsanitize=address -o test test.c + paxctl -a test + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"heap-buffer-overflow" ./test +} + +heap_overflow_profile_body() { + cat > test.c << EOF +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +int foo(int index) { int *x = (int *)malloc(20); int res = x[index * 4]; free(x); return res;} +int main(int argc, char **argv) {foo(argc + 19); printf("CHECK\n"); exit(0);} +EOF + cc -fsanitize=address -o test -pg test.c + paxctl +a test + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"heap-buffer-overflow" ./test +} + +heap_overflow_pic_body() { + cat > test.c << EOF +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +int foo(int); +int main(int argc, char **argv) {foo(argc + 19); printf("CHECK\n"); exit(0);} +EOF + cat > pic.c << EOF +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +int foo(int index) { int *x = (int *)malloc(20); int res = x[index * 4]; free(x); return res;} +EOF + + cc -fPIC -fsanitize=address -shared -o libtest.so pic.c + cc -o test test.c -fsanitize=address -L. -ltest + paxctl +a test + + export LD_LIBRARY_PATH=. + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"heap-buffer-overflow" ./test +} + +heap_overflow_pie_body() { + # check whether this arch supports -pice + if ! cc -pie -dM -E - < /dev/null 2>/dev/null >/dev/null; then + atf_set_skip "cc -pie not supported on this architecture" + fi + cat > test.c << EOF +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +int foo(int index) { int *x = (int *)malloc(20); int res = x[index * 4]; free(x); return res;} +int main(int argc, char **argv) {foo(argc + 19); printf("CHECK\n"); exit(0);} +EOF + cc -fsanitize=address -fpie -pie -o test test.c + paxctl +a test + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"heap-buffer-overflow" ./test +} + +heap_overflow32_body() { + # check whether this arch is 64bit + if ! cc -dM -E - < /dev/null | fgrep -q _LP64; then + atf_skip "this is not a 64 bit architecture" + fi + if ! cc -m32 -dM -E - < /dev/null 2>/dev/null > ./def32; then + atf_skip "cc -m32 not supported on this architecture" + else + if fgrep -q _LP64 ./def32; then + atf_fail "cc -m32 does not generate netbsd32 binaries" + fi +fi + + cat > test.c << EOF +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +int foo(int index) { int *x = (int *)malloc(20); int res = x[index * 4]; free(x); return res;} +int main(int argc, char **argv) {foo(argc + 19); printf("CHECK\n"); exit(0);} +EOF + cc -fsanitize=address -o ho32 -m32 test.c + cc -fsanitize=address -o ho64 test.c + file -b ./ho32 > ./ftype32 + file -b ./ho64 > ./ftype64 + if diff ./ftype32 ./ftype64 >/dev/null; then + atf_fail "generated binaries do not differ" + fi + echo "32bit binaries on this platform are:" + cat ./ftype32 + echo "While native (64bit) binaries are:" + cat ./ftype64 + paxctl +a ho32 + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"heap-buffer-overflow" ./ho32 + +# and another test with profile 32bit binaries + cat > test.c << EOF +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +int foo(int index) { int *x = (int *)malloc(20); int res = x[index * 4]; free(x); return res;} +int main(int argc, char **argv) {foo(argc + 19); printf("CHECK\n"); exit(0);} +EOF + cc -o test -m32 -fsanitize=address -pg test.c + paxctl +a test + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"heap-buffer-overflow" ./test +} + +target_not_supported_body() +{ + atf_skip "Target is not supported" +} + +atf_init_test_cases() +{ + test_target + test $SUPPORT = 'n' && { + atf_add_test_case target_not_supported + return 0 + } + + atf_add_test_case heap_overflow + atf_add_test_case heap_overflow_profile + atf_add_test_case heap_overflow_pic + atf_add_test_case heap_overflow_pie + atf_add_test_case heap_overflow32 + # static option not supported + # -static and -fsanitize=address can't be used together for compilation + # (gcc version 5.4.0 and clang 7.1) tested on April 2nd 2018. +} Index: src/tests/usr.bin/cc/t_asan_off_by_one.sh diff -u /dev/null src/tests/usr.bin/cc/t_asan_off_by_one.sh:1.1 --- /dev/null Wed Apr 4 23:51:35 2018 +++ src/tests/usr.bin/cc/t_asan_off_by_one.sh Wed Apr 4 23:51:35 2018 @@ -0,0 +1,233 @@ +# $NetBSD: t_asan_off_by_one.sh,v 1.1 2018/04/04 23:51:35 kamil Exp $ +# +# Copyright (c) 2018 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Siddharth Muralee. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +SUPPORT='n' +test_target() { + if uname -m | grep -q "amd64"; then + SUPPORT='y' + fi + + if uname -m | grep -q "i386"; then + SUPPORT='y' + fi +} + +atf_test_case off_by_one +off_by_one_head() { + atf_set "descr" "compile and run \"Off by one example\"" + atf_set "require.progs" "cc paxctl" +} + +atf_test_case off_by_one_profile +off_by_one_profile_head() { + atf_set "descr" "compile and run \"Off by one example\" with profiling option" + atf_set "require.progs" "cc paxctl" +} + +atf_test_case off_by_one_pic +off_by_one_pic_head() { + atf_set "descr" "compile and run PIC \"Off by one example\"" + atf_set "require.progs" "cc paxctl" +} + +atf_test_case off_by_one_pie +off_by_one_pie_head() { + atf_set "descr" "compile and run position independent (PIE) \"Off by one example\"" + atf_set "require.progs" "cc paxctl" +} + +atf_test_case off_by_one32 +off_by_one32_head() { + atf_set "descr" "compile and run \"Off by one example\" for/in netbsd32 emulation" + atf_set "require.progs" "cc paxctl file diff cat" +} + +atf_test_case target_not_supported +target_not_supported_head() +{ + atf_set "descr" "Test forced skip" +} + +off_by_one_body() { + cat > test.c << EOF +#include <stdio.h> +#include <stdlib.h> +void foo() { + int arr[5]; + for (int i = 0; i <= 5 ; i++) { + arr[i] = 0; + } +} +void main() {foo(); printf("CHECK\n"); exit(0);} +EOF + cc -fsanitize=address -o test test.c + paxctl +a test + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"stack-buffer-overflow" ./test +} + +off_by_one_profile_body() { + cat > test.c << EOF +#include <stdio.h> +#include <stdlib.h> +void foo() { + int arr[5]; + for (int i = 0; i <= 5 ; i++) { + arr[i] = 0; + } +} +void main() {foo(); printf("CHECK\n"); exit(0);} +EOF + cc -fsanitize=address -o test -pg test.c + paxctl +a test + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"stack-buffer-overflow" ./test +} + +off_by_one_pic_body() { + cat > test.c << EOF +#include <stdio.h> +#include <stdlib.h> +void foo(); +void main() {foo(); printf("CHECK\n"); exit(0);} +EOF + cat > pic.c << EOF +#include <stdio.h> +#include <stdlib.h> +void foo() { + int arr[5]; + for (int i = 0; i <= 5 ; i++) { + arr[i] = 0; + } +} +EOF + cc -fPIC -fsanitize=address -shared -o libtest.so pic.c + cc -o test test.c -fsanitize=address -L. -ltest + + export LD_LIBRARY_PATH=. + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"stack-buffer-overflow" ./test +} + +off_by_one_pie_body() { + # check whether this arch supports -pice + if ! cc -pie -dM -E - < /dev/null 2>/dev/null >/dev/null; then + atf_set_skip "cc -pie not supported on this architecture" + fi + cat > test.c << EOF +#include <stdio.h> +#include <stdlib.h> +void foo() { + int arr[5]; + for (int i = 0; i <= 5 ; i++) { + arr[i] = 0; + } +} +void main() {foo(); printf("CHECK\n"); exit(0);} +EOF + cc -fsanitize=address -o test -fpie -pie test.c + paxctl +a test + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"stack-buffer-overflow" ./test +} + +off_by_one32_body() { + # check whether this arch is 64bit + if ! cc -dM -E - < /dev/null | fgrep -q _LP64; then + atf_skip "this is not a 64 bit architecture" + fi + if ! cc -m32 -dM -E - < /dev/null 2>/dev/null > ./def32; then + atf_skip "cc -m32 not supported on this architecture" + else + if fgrep -q _LP64 ./def32; then + atf_fail "cc -m32 does not generate netbsd32 binaries" + fi +fi + + cat > test.c << EOF +#include <stdio.h> +#include <stdlib.h> +void foo() { + int arr[5]; + for (int i = 0; i <= 5 ; i++) { + arr[i] = 0; + } +} +void main() {foo(); printf("CHECK\n"); exit(0);} +EOF + cc -fsanitize=address -o obo32 -m32 test.c + cc -fsanitize=address -o obo64 test.c + file -b ./obo32 > ./ftype32 + file -b ./obo64 > ./ftype64 + if diff ./ftype32 ./ftype64 >/dev/null; then + atf_fail "generated binaries do not differ" + fi + echo "32bit binaries on this platform are:" + cat ./ftype32 + echo "While native (64bit) binaries are:" + cat ./ftype64 + paxctl +a obo32 + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"stack-buffer-overflow" ./obo32 + +# and another test with profile 32bit binaries + cat > test.c << EOF +#include <stdio.h> +#include <stdlib.h> +void foo() { + int arr[5]; + for (int i = 0; i <= 5 ; i++) { + arr[i] = 0; + } +} +void main() {foo(); printf("CHECK\n"); exit(0);} +EOF + cc -fsanitize=address -o test -pg test.c + paxctl +a test + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"stack-buffer-overflow" ./test +} + +target_not_supported_body() +{ + atf_skip "Target is not supported" +} + +atf_init_test_cases() +{ + test_target + test $SUPPORT = 'n' && { + atf_add_test_case target_not_supported + return 0 + } + + atf_add_test_case off_by_one + atf_add_test_case off_by_one_profile + atf_add_test_case off_by_one_pic + atf_add_test_case off_by_one_pie + atf_add_test_case off_by_one32 + # static option not supported + # -static and -fsanitize=address can't be used together for compilation + # (gcc version 5.4.0 and clang 7.1) tested on April 2nd 2018. +} Index: src/tests/usr.bin/cc/t_asan_uaf.sh diff -u /dev/null src/tests/usr.bin/cc/t_asan_uaf.sh:1.1 --- /dev/null Wed Apr 4 23:51:35 2018 +++ src/tests/usr.bin/cc/t_asan_uaf.sh Wed Apr 4 23:51:35 2018 @@ -0,0 +1,205 @@ +# $NetBSD: t_asan_uaf.sh,v 1.1 2018/04/04 23:51:35 kamil Exp $ +# +# Copyright (c) 2018 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Siddharth Muralee. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +SUPPORT='n' +test_target() { + if uname -m | grep -q "amd64"; then + SUPPORT='y' + fi + + if uname -m | grep -q "i386"; then + SUPPORT='y' + fi +} + +atf_test_case uaf +uaf_head() { + atf_set "descr" "compile and run \"Use After Free example\"" + atf_set "require.progs" "cc paxctl" +} + +atf_test_case uaf_profile +uaf_profile_head() { + atf_set "descr" "compile and run \"Use After Free example\" with profiling option" + atf_set "require.progs" "cc paxctl" +} + +atf_test_case uaf_pic +uaf_pic_head() { + atf_set "descr" "compile and run PIC \"Use After Free example\"" + atf_set "require.progs" "cc paxctl" +} + +atf_test_case uaf_pie +uaf_pie_head() { + atf_set "descr" "compile and run position independent (PIE) \"Use After Free example\"" + atf_set "require.progs" "cc paxctl" +} + +atf_test_case uaf32 +uaf32_head() { + atf_set "descr" "compile and run \"Use After Free example\" for/in netbsd32 emulation" + atf_set "require.progs" "cc paxctl file diff cat" +} + +atf_test_case target_not_supported +target_not_supported_head() +{ + atf_set "descr" "Test forced skip" +} + +uaf_body() { + cat > test.c << EOF +#include <stdlib.h> +#include <stdio.h> +int foo() {int *x = (int *)malloc(10 * sizeof(int)); free(x); return x[0];} +void main() {foo(); printf("CHECK\n"); exit(0);} +EOF + cc -fsanitize=address -o test test.c + paxctl +a test + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"heap-use-after-free" ./test +} + +uaf_profile_body() { + cat > test.c << EOF +#include <stdlib.h> +#include <stdio.h> +int foo() {int *x = (int *)malloc(10 * sizeof(int)); free(x); return x[0];} +void main() {foo(); printf("CHECK\n"); exit(0);} +EOF + cc -fsanitize=address -o test -pg test.c + paxctl +a test + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"heap-use-after-free" ./test +} + +uaf_pic_body() { + cat > test.c << EOF +#include <stdlib.h> +#include <stdio.h> +int foo(); +void main() {foo(); printf("CHECK\n"); exit(0);} +EOF + cat > pic.c << EOF +#include <stdlib.h> +#include <stdio.h> +int foo() {int *x = (int *)malloc(10 * sizeof(int)); free(x); return x[0];} +EOF + + cc -fPIC -fsanitize=address -shared -o libtest.so pic.c + cc -o test test.c -fsanitize=address -L. -ltest + paxctl +a test + + export LD_LIBRARY_PATH=. + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"heap-use-after-free" ./test +} + +uaf_pie_body() { + # check whether this arch supports -pice + if ! cc -pie -dM -E - < /dev/null 2>/dev/null >/dev/null; then + atf_set_skip "cc -pie not supported on this architecture" + fi + cat > test.c << EOF +#include <stdlib.h> +#include <stdio.h> +int foo() {int *x = (int *)malloc(10 * sizeof(int)); free(x); return x[0];} +void main() {foo(); printf("CHECK\n"); exit(0);} +EOF + cc -fsanitize=address -fpie -pie -o test test.c + paxctl +a test + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"heap-use-after-free" ./test +} + +uaf32_body() { + # check whether this arch is 64bit + if ! cc -dM -E - < /dev/null | fgrep -q _LP64; then + atf_skip "this is not a 64 bit architecture" + fi + if ! cc -m32 -dM -E - < /dev/null 2>/dev/null > ./def32; then + atf_skip "cc -m32 not supported on this architecture" + else + if fgrep -q _LP64 ./def32; then + atf_fail "cc -m32 does not generate netbsd32 binaries" + fi +fi + + cat > test.c << EOF +#include <stdlib.h> +#include <stdio.h> +int foo() {int *x = (int *)malloc(10 * sizeof(int)); free(x); return x[0];} +void main() {foo(); printf("CHECK\n"); exit(0);} +EOF + cc -fsanitize=address -o uaf32 -m32 test.c + cc -fsanitize=address -o uaf64 test.c + file -b ./uaf32 > ./ftype32 + file -b ./uaf64 > ./ftype64 + if diff ./ftype32 ./ftype64 >/dev/null; then + atf_fail "generated binaries do not differ" + fi + echo "32bit binaries on this platform are:" + cat ./ftype32 + echo "While native (64bit) binaries are:" + cat ./ftype64 + paxctl +a uaf32 + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"heap-use-after-free" ./uaf32 + +# and another test with profile 32bit binaries + cat > test.c << EOF +#include <stdlib.h> +#include <stdio.h> +int foo() {int *x = (int *)malloc(10 * sizeof(int)); free(x); return x[0];} +void main() {foo(); printf("CHECK\n"); exit(0);} +EOF + cc -o test -m32 -fsanitize=address -pg test.c + paxctl +a test + atf_check -s not-exit:0 -o not-match:"CHECK\n" -e match:"heap-use-after-free" ./test +} + +target_not_supported_body() +{ + atf_skip "Target is not supported" +} + +atf_init_test_cases() +{ + test_target + test $SUPPORT = 'n' && { + atf_add_test_case target_not_supported + return 0 + } + + atf_add_test_case uaf + atf_add_test_case uaf_profile + atf_add_test_case uaf_pic + atf_add_test_case uaf_pie + atf_add_test_case uaf32 + # static option not supported + # -static and -fsanitize=address can't be used together for compilation + # (gcc version 5.4.0 and clang 7.1) tested on April 2nd 2018. +}