t_tsan_heap_use_after_free.sh revision 1.4
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
29tsan_available_archs()
30{
31	atf_set "require.arch" "x86_64"
32}
33
34test_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
51atf_test_case heap_use_after_free
52heap_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
58atf_test_case heap_use_after_free_profile
59heap_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}
64atf_test_case heap_use_after_free_pic
65heap_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}
70atf_test_case heap_use_after_free_pie
71heap_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
77heap_use_after_free_body(){
78	cat > test.cc << EOF
79#include <pthread.h>
80#include <stdlib.h>
81
82int *ptr;
83pthread_barrier_t barrier;
84void *Thread(void *a) {
85  pthread_barrier_wait(&barrier);
86  *ptr = 42;
87  return 0;
88}
89
90int 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}
100EOF
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
107heap_use_after_free_profile_body(){
108	cat > test.cc << EOF
109#include <pthread.h>
110#include <stdlib.h>
111
112int *ptr;
113pthread_barrier_t barrier;
114void *Thread(void *a) {
115  pthread_barrier_wait(&barrier);
116  *ptr = 42;
117  return 0;
118}
119
120int main() {
121  pthread_t t;
122  pthread_barrier_init(&barrier, NULL, 2);
123  ptr = (int *)malloc(sizeof(int));
124  pthread_create(&t, NULL, Thread, NULL);
125  free(ptr);
126  pthread_barrier_wait(&barrier);
127  pthread_join(t, NULL);
128  return 0;
129}
130EOF
131
132	c++ -fsanitize=thread -o test -pg test.cc
133	paxctl +a test
134	atf_check -s ignore -o ignore -e match:"WARNING: ThreadSanitizer: heap-use-after-free" ./test
135}
136
137heap_use_after_free_pic_body(){
138	cat > test.cc << EOF
139#include <stdio.h>
140#include <stdlib.h>
141int help(int);
142int main(int argc, char **argv) {return help(argc);}
143EOF
144
145	cat > pic.cc << EOF
146#include <pthread.h>
147#include <stdlib.h>
148
149int *ptr;
150pthread_barrier_t barrier;
151void *Thread(void *a) {
152  pthread_barrier_wait(&barrier);
153  *ptr = 42;
154  return 0;
155}
156
157int help(int argc) {
158  pthread_t t;
159  pthread_barrier_init(&barrier, NULL, 2);
160  ptr = (int *)malloc(sizeof(int));
161  pthread_create(&t, NULL, Thread, NULL);
162  free(ptr);
163  pthread_barrier_wait(&barrier);
164  pthread_join(t, NULL);
165  return 0;
166}
167EOF
168
169	c++ -fsanitize=thread -fPIC -shared -o libtest.so pic.cc
170	c++ -o test test.cc -fsanitize=thread -L. -ltest
171	paxctl +a test
172
173	export LD_LIBRARY_PATH=.
174	atf_check -s ignore -o ignore -e match:"WARNING: ThreadSanitizer: heap-use-after-free" ./test
175}
176heap_use_after_free_pie_body(){
177	
178	#check whether -pie flag is supported on this architecture
179	if ! c++ -pie -dM -E - < /dev/null 2>/dev/null >/dev/null; then 
180		atf_set_skip "c++ -pie not supported on this architecture"
181	fi
182	cat > test.cc << EOF
183#include <pthread.h>
184#include <stdlib.h>
185
186int *ptr;
187pthread_barrier_t barrier;
188void *Thread(void *a) {
189  pthread_barrier_wait(&barrier);
190  *ptr = 42;
191  return 0;
192}
193
194int main() {
195  pthread_t t;
196  pthread_barrier_init(&barrier, NULL, 2);
197  ptr = (int *)malloc(sizeof(int));
198  pthread_create(&t, NULL, Thread, NULL);
199  free(ptr);
200  pthread_barrier_wait(&barrier);
201  pthread_join(t, NULL);
202  return 0;
203}
204EOF
205
206	c++ -fsanitize=thread -o test -fpie -pie test.cc
207	paxctl +a test
208	atf_check -s ignore -o ignore -e match:"WARNING: ThreadSanitizer: heap-use-after-free" ./test
209}
210
211
212atf_init_test_cases()
213{
214	atf_add_test_case heap_use_after_free
215	atf_add_test_case heap_use_after_free_profile
216	atf_add_test_case heap_use_after_free_pie
217	atf_add_test_case heap_use_after_free_pic
218}
219