1#!/bin/sh 2 3# 4# SPDX-License-Identifier: BSD-2-Clause 5# 6# Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> 7# 8# Redistribution and use in source and binary forms, with or without 9# modification, are permitted provided that the following conditions 10# are met: 11# 1. Redistributions of source code must retain the above copyright 12# notice, this list of conditions and the following disclaimer. 13# 2. Redistributions in binary form must reproduce the above copyright 14# notice, this list of conditions and the following disclaimer in the 15# documentation and/or other materials provided with the distribution. 16# 17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27# SUCH DAMAGE. 28# 29 30# Deadlock seen: https://people.freebsd.org/~pho/stress/log/mark169.txt 31# Test scenario based on the syzkaller reproducer syzkaller21.sh and comments 32# by markj@. 33 34. ../default.cfg 35[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1 36 37dir=/tmp 38odir=`pwd` 39cd $dir 40sed '1,/^EOF/d' < $odir/$0 > $dir/fsync2.c 41mycc -o fsync2 -Wall -Wextra -O0 -g fsync2.c -lpthread || exit 1 42rm -f fsync2.c 43cd $odir 44 45set -e 46mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint 47[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart 48mdconfig -a -t swap -s 2g -u $mdstart 49newfs $newfs_flags md$mdstart > /dev/null 50mount /dev/md$mdstart $mntpoint 51set +e 52 53(cd $mntpoint; $dir/fsync2) 54 55for i in `jot 6`; do 56 mount | grep -q "on $mntpoint " || break 57 umount $mntpoint && break || sleep 10 58 [ $i -eq 6 ] && 59 { echo FATAL; fstat -mf $mntpoint; exit 1; } 60done 61mdconfig -d -u $mdstart 62rm -rf $dir/fsync2 63exit 0 64EOF 65#include <sys/types.h> 66#include <sys/stat.h> 67 68#include <err.h> 69#include <fcntl.h> 70#include <pthread.h> 71#include <signal.h> 72#include <stdio.h> 73#include <stdlib.h> 74#include <string.h> 75#include <unistd.h> 76 77#define RUNTIME 60 78 79static time_t start; 80static volatile int fd; 81 82static void * 83t1(void *data __unused) 84{ 85 char cwd[1024]; 86 87 if (getcwd(cwd, sizeof(cwd)) == NULL) 88 err(1, "getcwd()"); 89 while (time(NULL) - start < RUNTIME) { 90 if (mkdir("./file0", 0740) == -1) 91 err(1, "mkdir(file0)"); 92 if (mkdir("./file1", 0740) == -1) 93 err(1, "mkdir(file2)"); 94 if (rename("./file1", "./file0/file0") == -1) 95 err(1, "rename()"); 96 if ((fd = open("./file0/file0", O_RDONLY)) == -1) 97 err(1, "open()"); 98 if (chdir("./file0/file0") == -1) 99 err(1, "chdir()"); 100 if (chdir(cwd) == -1) 101 err(1, "chdir(HOME)"); 102 close(fd); 103 rmdir("./file0/file0"); 104 rmdir("./file0"); 105 } 106 107 return (NULL); 108} 109 110static void * 111t2(void *data __unused) 112{ 113 while (time(NULL) - start < RUNTIME) { 114 fsync(fd); 115 } 116 117 return (NULL); 118} 119 120int 121main(void) 122{ 123 pthread_t tid[2]; 124 int r; 125 126 start = time(NULL); 127 if ((r = pthread_create(&tid[0], NULL, t1, NULL)) != 0) 128 errc(1, r, "pthread_create"); 129 if ((r = pthread_create(&tid[1], NULL, t2, NULL)) != 0) 130 errc(1, r, "pthread_create"); 131 132 if ((r = pthread_join(tid[0], NULL)) != 0) 133 errc(1, r, "pthread_join"); 134 if ((r = pthread_join(tid[1], NULL)) != 0) 135 errc(1, r, "pthread_join"); 136 137 return (0); 138} 139