Home | History | Annotate | Line # | Download | only in c++
      1 # Copyright (c) 2018 The NetBSD Foundation, Inc.
      2 # All rights reserved.
      3 #
      4 # This code is derived from software contributed to The NetBSD Foundation
      5 # by Yang Zheng.
      6 #
      7 # Redistribution and use in source and binary forms, with or without
      8 # modification, are permitted provided that the following conditions
      9 # are met:
     10 # 1. Redistributions of source code must retain the above copyright
     11 #    notice, this list of conditions and the following disclaimer.
     12 # 2. Redistributions in binary form must reproduce the above copyright
     13 #    notice, this list of conditions and the following disclaimer in the
     14 #    documentation and/or other materials provided with the distribution.
     15 #
     16 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19 # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26 # POSSIBILITY OF SUCH DAMAGE.
     27 #
     28 
     29 tsan_available_archs()
     30 {
     31 	atf_set "require.arch" "x86_64"
     32 }
     33 
     34 test_target()
     35 {
     36 	SUPPORT='n'
     37 	# Detect address space larger than 32 bits
     38 	maxaddress=`sysctl vm.maxaddress|awk '{print $3}'`
     39 	if [ $maxaddress -gt 4294967295 ]; then
     40 		if command -v cc >/dev/null 2>&1; then
     41 			if ! echo __clang__ | cc -E - | grep -q __clang__; then
     42 				SUPPORT='y'
     43 			elif ! cc -v 2>&1 | awk '/gcc version/{print $3}' | \
     44 				awk -F '.' '($0+0) > 9 {exit 1}'; then
     45 				SUPPORT='y'
     46 			fi
     47 		fi
     48 	fi
     49 }
     50 
     51 atf_test_case heap_use_after_free
     52 heap_use_after_free_head() {
     53 	atf_set "descr" "Test thread sanitizer for use-after-free condition"
     54 	atf_set "require.progs" "c++ paxctl"
     55 	tsan_available_archs
     56 }
     57 
     58 atf_test_case heap_use_after_free_profile
     59 heap_use_after_free_profile_head() {
     60 	atf_set "descr" "Test thread sanitizer for use-after-free with profiling option"
     61 	atf_set "require.progs" "c++ paxctl"
     62 	tsan_available_archs
     63 }
     64 atf_test_case heap_use_after_free_pic
     65 heap_use_after_free_pic_head() {
     66 	atf_set "descr" "Test thread sanitizer for use-after-free with position independent code (PIC) flag"
     67 	atf_set "require.progs" "c++ paxctl"
     68 	tsan_available_archs
     69 }
     70 atf_test_case heap_use_after_free_pie
     71 heap_use_after_free_pie_head() {
     72 	atf_set "descr" "Test thread sanitizer for use-after-free with position independent execution (PIE) flag"
     73 	atf_set "require.progs" "c++ paxctl"
     74 	tsan_available_archs
     75 }
     76 
     77 heap_use_after_free_body(){
     78 	cat > test.cc << EOF
     79 #include <pthread.h>
     80 #include <stdlib.h>
     81 
     82 int *ptr;
     83 pthread_barrier_t barrier;
     84 void *Thread(void *a) {
     85   pthread_barrier_wait(&barrier);
     86   *ptr = 42;
     87   return 0;
     88 }
     89 
     90 int main() {
     91   pthread_t t;
     92   pthread_barrier_init(&barrier, NULL, 2);
     93   ptr = (int *)malloc(sizeof(int));
     94   pthread_create(&t, NULL, Thread, NULL);
     95   free(ptr);
     96   pthread_barrier_wait(&barrier);
     97   pthread_join(t, NULL);
     98   return 0;
     99 }
    100 EOF
    101 
    102 	c++ -fsanitize=thread -o test test.cc
    103 	paxctl +a test
    104 	atf_check -s ignore -o ignore -e match:"WARNING: ThreadSanitizer: heap-use-after-free" ./test
    105 }
    106 
    107 heap_use_after_free_profile_body(){
    108 	atf_expect_fail "PR toolchain/55760"
    109 	cat > test.cc << EOF
    110 #include <pthread.h>
    111 #include <stdlib.h>
    112 
    113 int *ptr;
    114 pthread_barrier_t barrier;
    115 void *Thread(void *a) {
    116   pthread_barrier_wait(&barrier);
    117   *ptr = 42;
    118   return 0;
    119 }
    120 
    121 int main() {
    122   pthread_t t;
    123   pthread_barrier_init(&barrier, NULL, 2);
    124   ptr = (int *)malloc(sizeof(int));
    125   pthread_create(&t, NULL, Thread, NULL);
    126   free(ptr);
    127   pthread_barrier_wait(&barrier);
    128   pthread_join(t, NULL);
    129   return 0;
    130 }
    131 EOF
    132 
    133 	c++ -fsanitize=thread -static -o test -pg test.cc
    134 	paxctl +a test
    135 	atf_check -s ignore -o ignore -e match:"WARNING: ThreadSanitizer: heap-use-after-free" ./test
    136 }
    137 
    138 heap_use_after_free_pic_body(){
    139 	cat > test.cc << EOF
    140 #include <stdio.h>
    141 #include <stdlib.h>
    142 int help(int);
    143 int main(int argc, char **argv) {return help(argc);}
    144 EOF
    145 
    146 	cat > pic.cc << EOF
    147 #include <pthread.h>
    148 #include <stdlib.h>
    149 
    150 int *ptr;
    151 pthread_barrier_t barrier;
    152 void *Thread(void *a) {
    153   pthread_barrier_wait(&barrier);
    154   *ptr = 42;
    155   return 0;
    156 }
    157 
    158 int help(int argc) {
    159   pthread_t t;
    160   pthread_barrier_init(&barrier, NULL, 2);
    161   ptr = (int *)malloc(sizeof(int));
    162   pthread_create(&t, NULL, Thread, NULL);
    163   free(ptr);
    164   pthread_barrier_wait(&barrier);
    165   pthread_join(t, NULL);
    166   return 0;
    167 }
    168 EOF
    169 
    170 	c++ -fsanitize=thread -fPIC -shared -o libtest.so pic.cc
    171 	c++ -o test test.cc -fsanitize=thread -L. -ltest
    172 	paxctl +a test
    173 
    174 	export LD_LIBRARY_PATH=.
    175 	atf_check -s ignore -o ignore -e match:"WARNING: ThreadSanitizer: heap-use-after-free" ./test
    176 }
    177 heap_use_after_free_pie_body(){
    178 
    179 	#check whether -pie flag is supported on this architecture
    180 	if ! c++ -pie -dM -E - < /dev/null 2>/dev/null >/dev/null; then
    181 		atf_set_skip "c++ -pie not supported on this architecture"
    182 	fi
    183 	cat > test.cc << EOF
    184 #include <pthread.h>
    185 #include <stdlib.h>
    186 
    187 int *ptr;
    188 pthread_barrier_t barrier;
    189 void *Thread(void *a) {
    190   pthread_barrier_wait(&barrier);
    191   *ptr = 42;
    192   return 0;
    193 }
    194 
    195 int main() {
    196   pthread_t t;
    197   pthread_barrier_init(&barrier, NULL, 2);
    198   ptr = (int *)malloc(sizeof(int));
    199   pthread_create(&t, NULL, Thread, NULL);
    200   free(ptr);
    201   pthread_barrier_wait(&barrier);
    202   pthread_join(t, NULL);
    203   return 0;
    204 }
    205 EOF
    206 
    207 	c++ -fsanitize=thread -o test -fpie -pie test.cc
    208 	paxctl +a test
    209 	atf_check -s ignore -o ignore -e match:"WARNING: ThreadSanitizer: heap-use-after-free" ./test
    210 }
    211 
    212 
    213 atf_init_test_cases()
    214 {
    215 	atf_add_test_case heap_use_after_free
    216 	atf_add_test_case heap_use_after_free_profile
    217 	atf_add_test_case heap_use_after_free_pie
    218 	atf_add_test_case heap_use_after_free_pic
    219 }
    220