t_tsan_lock_order_inversion.sh revision 1.2
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
29test_target()
30{
31	SUPPORT='n'
32	if uname -m | grep -q "amd64" && command -v cc >/dev/null 2>&1 && \
33		   ! echo __clang__ | cc -E - | grep -q __clang__; then
34		# only clang with major version newer than 7 is supported
35		CLANG_MAJOR=`echo __clang_major__ | cc -E - | grep -o '^[[:digit:]]'`
36		if [ "$CLANG_MAJOR" -ge "7" ]; then
37			SUPPORT='y'
38		fi
39	fi
40}
41
42atf_test_case lock_order_inversion
43lock_order_inversion_head() {
44	atf_set "descr" "Test thread sanitizer for lock order inversion condition"
45	atf_set "require.progs" "cc paxctl"
46}
47
48atf_test_case lock_order_inversion_profile
49lock_order_inversion_profile_head() {
50	atf_set "descr" "Test thread sanitizer for lock order inversion with profiling option"
51	atf_set "require.progs" "cc paxctl"
52}
53atf_test_case lock_order_inversion_pic
54lock_order_inversion_pic_head() {
55	atf_set "descr" "Test thread sanitizer for lock order inversion with position independent code (PIC) flag"
56	atf_set "require.progs" "cc paxctl"
57}
58atf_test_case lock_order_inversion_pie
59lock_order_inversion_pie_head() {
60	atf_set "descr" "Test thread sanitizer for lock order inversion with position independent execution (PIE) flag"
61	atf_set "require.progs" "cc paxctl"
62}
63
64lock_order_inversion_body(){
65	cat > test.c << EOF
66#include <pthread.h>
67
68pthread_mutex_t l1, l2;
69int main() {
70  pthread_mutex_init(&l1, NULL);
71  pthread_mutex_init(&l2, NULL);
72  pthread_mutex_lock(&l2);
73  pthread_mutex_lock(&l1);
74  pthread_mutex_unlock(&l1);
75  pthread_mutex_unlock(&l2);
76
77  pthread_mutex_lock(&l1);
78  pthread_mutex_lock(&l2);
79  pthread_mutex_unlock(&l2);
80  pthread_mutex_unlock(&l1);
81  return 0;
82}
83EOF
84
85	cc -fsanitize=thread -o test test.c
86	paxctl +a test
87	atf_check -s ignore -o ignore -e match:"WARNING: ThreadSanitizer: lock-order-inversion" ./test
88}
89
90lock_order_inversion_profile_body(){
91	cat > test.c << EOF
92#include <pthread.h>
93
94pthread_mutex_t l1, l2;
95int main() {
96  pthread_mutex_init(&l1, NULL);
97  pthread_mutex_init(&l2, NULL);
98  pthread_mutex_lock(&l2);
99  pthread_mutex_lock(&l1);
100  pthread_mutex_unlock(&l1);
101  pthread_mutex_unlock(&l2);
102
103  pthread_mutex_lock(&l1);
104  pthread_mutex_lock(&l2);
105  pthread_mutex_unlock(&l2);
106  pthread_mutex_unlock(&l1);
107  return 0;
108}
109EOF
110
111	cc -fsanitize=thread -o test -pg test.c
112	paxctl +a test
113	atf_check -s ignore -o ignore -e match:"WARNING: ThreadSanitizer: lock-order-inversion" ./test
114}
115
116lock_order_inversion_pic_body(){
117	cat > test.c << EOF
118#include <stdio.h>
119#include <stdlib.h>
120int help(int);
121int main(int argc, char **argv) {return help(argc);}
122EOF
123
124	cat > pic.c << EOF
125#include <pthread.h>
126
127pthread_mutex_t l1, l2;
128int help(int argc) {
129  pthread_mutex_init(&l1, NULL);
130  pthread_mutex_init(&l2, NULL);
131  pthread_mutex_lock(&l2);
132  pthread_mutex_lock(&l1);
133  pthread_mutex_unlock(&l1);
134  pthread_mutex_unlock(&l2);
135
136  pthread_mutex_lock(&l1);
137  pthread_mutex_lock(&l2);
138  pthread_mutex_unlock(&l2);
139  pthread_mutex_unlock(&l1);
140  return 0;
141}
142EOF
143
144	cc -fsanitize=thread -fPIC -shared -o libtest.so pic.c
145	cc -o test test.c -fsanitize=thread -L. -ltest
146	paxctl +a test
147
148	export LD_LIBRARY_PATH=.
149	atf_check -s ignore -o ignore -e match:"WARNING: ThreadSanitizer: lock-order-inversion" ./test
150}
151lock_order_inversion_pie_body(){
152	
153	#check whether -pie flag is supported on this architecture
154	if ! cc -pie -dM -E - < /dev/null 2>/dev/null >/dev/null; then 
155		atf_set_skip "cc -pie not supported on this architecture"
156	fi
157	cat > test.c << EOF
158#include <pthread.h>
159
160pthread_mutex_t l1, l2;
161int main() {
162  pthread_mutex_init(&l1, NULL);
163  pthread_mutex_init(&l2, NULL);
164  pthread_mutex_lock(&l2);
165  pthread_mutex_lock(&l1);
166  pthread_mutex_unlock(&l1);
167  pthread_mutex_unlock(&l2);
168
169  pthread_mutex_lock(&l1);
170  pthread_mutex_lock(&l2);
171  pthread_mutex_unlock(&l2);
172  pthread_mutex_unlock(&l1);
173  return 0;
174}
175EOF
176
177	cc -fsanitize=thread -o test -fpie -pie test.c
178	paxctl +a test
179	atf_check -s ignore -o ignore -e match:"WARNING: ThreadSanitizer: lock-order-inversion" ./test
180}
181
182
183atf_test_case target_not_supported
184target_not_supported_head()
185{
186	atf_set "descr" "Test forced skip"
187}
188
189target_not_supported_body()
190{
191	atf_skip "Target is not supported"
192}
193
194atf_init_test_cases()
195{
196	test_target
197	test $SUPPORT = 'n' && {
198		atf_add_test_case target_not_supported
199		return 0
200	}
201	atf_add_test_case lock_order_inversion
202	atf_add_test_case lock_order_inversion_profile
203	atf_add_test_case lock_order_inversion_pie
204	atf_add_test_case lock_order_inversion_pic
205}
206