11.1Skamil# Copyright (c) 2018 The NetBSD Foundation, Inc.
21.1Skamil# All rights reserved.
31.1Skamil#
41.1Skamil# This code is derived from software contributed to The NetBSD Foundation
51.1Skamil# by Yang Zheng.
61.1Skamil#
71.1Skamil# Redistribution and use in source and binary forms, with or without
81.1Skamil# modification, are permitted provided that the following conditions
91.1Skamil# are met:
101.1Skamil# 1. Redistributions of source code must retain the above copyright
111.1Skamil#    notice, this list of conditions and the following disclaimer.
121.1Skamil# 2. Redistributions in binary form must reproduce the above copyright
131.1Skamil#    notice, this list of conditions and the following disclaimer in the
141.1Skamil#    documentation and/or other materials provided with the distribution.
151.1Skamil#
161.1Skamil# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
171.1Skamil# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
181.1Skamil# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
191.1Skamil# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
201.1Skamil# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
211.1Skamil# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
221.1Skamil# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
231.1Skamil# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
241.1Skamil# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
251.1Skamil# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
261.1Skamil# POSSIBILITY OF SUCH DAMAGE.
271.1Skamil#
281.1Skamil
291.4Smartintsan_available_archs()
301.4Smartin{
311.4Smartin	atf_set "require.arch" "x86_64"
321.4Smartin}
331.4Smartin
341.1Skamiltest_target()
351.1Skamil{
361.1Skamil	SUPPORT='n'
371.3Skamil	# Detect address space larger than 32 bits
381.3Skamil	maxaddress=`sysctl vm.maxaddress|awk '{print $3}'`
391.3Skamil	if [ $maxaddress -gt 4294967295 ]; then
401.3Skamil		if command -v cc >/dev/null 2>&1; then
411.3Skamil			if ! echo __clang__ | cc -E - | grep -q __clang__; then
421.3Skamil				SUPPORT='y'
431.3Skamil			elif ! cc -v 2>&1 | awk '/gcc version/{print $3}' | \
441.3Skamil				awk -F '.' '($0+0) > 9 {exit 1}'; then
451.3Skamil				SUPPORT='y'
461.3Skamil			fi
471.1Skamil		fi
481.1Skamil	fi
491.1Skamil}
501.1Skamil
511.1Skamilatf_test_case heap_use_after_free
521.1Skamilheap_use_after_free_head() {
531.1Skamil	atf_set "descr" "Test thread sanitizer for use-after-free condition"
541.1Skamil	atf_set "require.progs" "c++ paxctl"
551.4Smartin	tsan_available_archs
561.1Skamil}
571.1Skamil
581.1Skamilatf_test_case heap_use_after_free_profile
591.1Skamilheap_use_after_free_profile_head() {
601.1Skamil	atf_set "descr" "Test thread sanitizer for use-after-free with profiling option"
611.1Skamil	atf_set "require.progs" "c++ paxctl"
621.4Smartin	tsan_available_archs
631.1Skamil}
641.1Skamilatf_test_case heap_use_after_free_pic
651.1Skamilheap_use_after_free_pic_head() {
661.1Skamil	atf_set "descr" "Test thread sanitizer for use-after-free with position independent code (PIC) flag"
671.1Skamil	atf_set "require.progs" "c++ paxctl"
681.4Smartin	tsan_available_archs
691.1Skamil}
701.1Skamilatf_test_case heap_use_after_free_pie
711.1Skamilheap_use_after_free_pie_head() {
721.1Skamil	atf_set "descr" "Test thread sanitizer for use-after-free with position independent execution (PIE) flag"
731.1Skamil	atf_set "require.progs" "c++ paxctl"
741.4Smartin	tsan_available_archs
751.1Skamil}
761.1Skamil
771.1Skamilheap_use_after_free_body(){
781.1Skamil	cat > test.cc << EOF
791.1Skamil#include <pthread.h>
801.1Skamil#include <stdlib.h>
811.1Skamil
821.1Skamilint *ptr;
831.1Skamilpthread_barrier_t barrier;
841.1Skamilvoid *Thread(void *a) {
851.1Skamil  pthread_barrier_wait(&barrier);
861.1Skamil  *ptr = 42;
871.1Skamil  return 0;
881.1Skamil}
891.1Skamil
901.1Skamilint main() {
911.1Skamil  pthread_t t;
921.1Skamil  pthread_barrier_init(&barrier, NULL, 2);
931.1Skamil  ptr = (int *)malloc(sizeof(int));
941.1Skamil  pthread_create(&t, NULL, Thread, NULL);
951.1Skamil  free(ptr);
961.1Skamil  pthread_barrier_wait(&barrier);
971.1Skamil  pthread_join(t, NULL);
981.1Skamil  return 0;
991.1Skamil}
1001.1SkamilEOF
1011.1Skamil
1021.1Skamil	c++ -fsanitize=thread -o test test.cc
1031.1Skamil	paxctl +a test
1041.1Skamil	atf_check -s ignore -o ignore -e match:"WARNING: ThreadSanitizer: heap-use-after-free" ./test
1051.1Skamil}
1061.1Skamil
1071.1Skamilheap_use_after_free_profile_body(){
1081.5Sgson	atf_expect_fail "PR toolchain/55760"
1091.1Skamil	cat > test.cc << EOF
1101.1Skamil#include <pthread.h>
1111.1Skamil#include <stdlib.h>
1121.1Skamil
1131.1Skamilint *ptr;
1141.1Skamilpthread_barrier_t barrier;
1151.1Skamilvoid *Thread(void *a) {
1161.1Skamil  pthread_barrier_wait(&barrier);
1171.1Skamil  *ptr = 42;
1181.1Skamil  return 0;
1191.1Skamil}
1201.1Skamil
1211.1Skamilint main() {
1221.1Skamil  pthread_t t;
1231.1Skamil  pthread_barrier_init(&barrier, NULL, 2);
1241.1Skamil  ptr = (int *)malloc(sizeof(int));
1251.1Skamil  pthread_create(&t, NULL, Thread, NULL);
1261.1Skamil  free(ptr);
1271.1Skamil  pthread_barrier_wait(&barrier);
1281.1Skamil  pthread_join(t, NULL);
1291.1Skamil  return 0;
1301.1Skamil}
1311.1SkamilEOF
1321.1Skamil
1331.7Sskrll	c++ -fsanitize=thread -static -o test -pg test.cc
1341.1Skamil	paxctl +a test
1351.1Skamil	atf_check -s ignore -o ignore -e match:"WARNING: ThreadSanitizer: heap-use-after-free" ./test
1361.1Skamil}
1371.1Skamil
1381.1Skamilheap_use_after_free_pic_body(){
1391.1Skamil	cat > test.cc << EOF
1401.1Skamil#include <stdio.h>
1411.1Skamil#include <stdlib.h>
1421.1Skamilint help(int);
1431.1Skamilint main(int argc, char **argv) {return help(argc);}
1441.1SkamilEOF
1451.1Skamil
1461.1Skamil	cat > pic.cc << EOF
1471.1Skamil#include <pthread.h>
1481.1Skamil#include <stdlib.h>
1491.1Skamil
1501.1Skamilint *ptr;
1511.1Skamilpthread_barrier_t barrier;
1521.1Skamilvoid *Thread(void *a) {
1531.1Skamil  pthread_barrier_wait(&barrier);
1541.1Skamil  *ptr = 42;
1551.1Skamil  return 0;
1561.1Skamil}
1571.1Skamil
1581.1Skamilint help(int argc) {
1591.1Skamil  pthread_t t;
1601.1Skamil  pthread_barrier_init(&barrier, NULL, 2);
1611.1Skamil  ptr = (int *)malloc(sizeof(int));
1621.1Skamil  pthread_create(&t, NULL, Thread, NULL);
1631.1Skamil  free(ptr);
1641.1Skamil  pthread_barrier_wait(&barrier);
1651.1Skamil  pthread_join(t, NULL);
1661.1Skamil  return 0;
1671.1Skamil}
1681.1SkamilEOF
1691.1Skamil
1701.1Skamil	c++ -fsanitize=thread -fPIC -shared -o libtest.so pic.cc
1711.1Skamil	c++ -o test test.cc -fsanitize=thread -L. -ltest
1721.1Skamil	paxctl +a test
1731.1Skamil
1741.1Skamil	export LD_LIBRARY_PATH=.
1751.1Skamil	atf_check -s ignore -o ignore -e match:"WARNING: ThreadSanitizer: heap-use-after-free" ./test
1761.1Skamil}
1771.1Skamilheap_use_after_free_pie_body(){
1781.6Sskrll
1791.1Skamil	#check whether -pie flag is supported on this architecture
1801.6Sskrll	if ! c++ -pie -dM -E - < /dev/null 2>/dev/null >/dev/null; then
1811.1Skamil		atf_set_skip "c++ -pie not supported on this architecture"
1821.1Skamil	fi
1831.1Skamil	cat > test.cc << EOF
1841.1Skamil#include <pthread.h>
1851.1Skamil#include <stdlib.h>
1861.1Skamil
1871.1Skamilint *ptr;
1881.1Skamilpthread_barrier_t barrier;
1891.1Skamilvoid *Thread(void *a) {
1901.1Skamil  pthread_barrier_wait(&barrier);
1911.1Skamil  *ptr = 42;
1921.1Skamil  return 0;
1931.1Skamil}
1941.1Skamil
1951.1Skamilint main() {
1961.1Skamil  pthread_t t;
1971.1Skamil  pthread_barrier_init(&barrier, NULL, 2);
1981.1Skamil  ptr = (int *)malloc(sizeof(int));
1991.1Skamil  pthread_create(&t, NULL, Thread, NULL);
2001.1Skamil  free(ptr);
2011.1Skamil  pthread_barrier_wait(&barrier);
2021.1Skamil  pthread_join(t, NULL);
2031.1Skamil  return 0;
2041.1Skamil}
2051.1SkamilEOF
2061.1Skamil
2071.1Skamil	c++ -fsanitize=thread -o test -fpie -pie test.cc
2081.1Skamil	paxctl +a test
2091.1Skamil	atf_check -s ignore -o ignore -e match:"WARNING: ThreadSanitizer: heap-use-after-free" ./test
2101.1Skamil}
2111.1Skamil
2121.1Skamil
2131.1Skamilatf_init_test_cases()
2141.1Skamil{
2151.1Skamil	atf_add_test_case heap_use_after_free
2161.1Skamil	atf_add_test_case heap_use_after_free_profile
2171.1Skamil	atf_add_test_case heap_use_after_free_pie
2181.1Skamil	atf_add_test_case heap_use_after_free_pic
2191.1Skamil}
220