1#!/bin/sh 2 3# 4# SPDX-License-Identifier: BSD-2-Clause 5# 6# Copyright (c) 2019 Dell EMC Isilon 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# "panic: caller failed to provide space -546873344 at address 0x20a00000" 31# seen. 32# https://people.freebsd.org/~pho/stress/log/indir_trunc.txt 33# Fixed by r348968 34 35# Test scenario inspired by: 36# syzbot+6532e9aab8911f58beeb@syzkaller.appspotmail.com 37 38. ../default.cfg 39[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1 40 41dir=/tmp 42odir=`pwd` 43cd $dir 44sed '1,/^EOF/d' < $odir/$0 > $dir/mmap34.c 45mycc -o mmap34 -Wall -Wextra -O0 -g mmap34.c -lpthread || exit 1 46cd $odir 47 48set -e 49mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint 50[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart 51mdconfig -a -t swap -s 4g -u $mdstart 52newfs $newfs_flags -n md$mdstart > /dev/null 53mount /dev/md$mdstart $mntpoint 54set +e 55 56(cd ../testcases/swap; ./swap -t 5m -i 20) & 57cd $mntpoint 58$dir/mmap34 59s=$? 60while pkill swap; do :; done 61wait 62[ -f mmap34.core ] && 63 { ls -l mmap34.core; mv mmap34.core $dir; s=1; } 64cd $odir 65 66for i in `jot 6`; do 67 mount | grep -q "on $mntpoint " || break 68 umount $mntpoint && break || sleep 10 69 [ $i -eq 6 ] && 70 { echo FATAL; fstat -mf $mntpoint; exit 1; } 71done 72mdconfig -d -u $mdstart 73rm -f $dir/mmap34 74[ $s -eq 0 ] && rm -f /tmp/mmap34.c 75exit $s 76 77EOF 78#include <sys/param.h> 79#include <sys/mman.h> 80#include <sys/stat.h> 81#include <sys/wait.h> 82 83#include <machine/atomic.h> 84 85#include <err.h> 86#include <errno.h> 87#include <fcntl.h> 88#include <pthread.h> 89#include <stdio.h> 90#include <stdlib.h> 91#include <time.h> 92#include <unistd.h> 93 94static volatile u_int *share; 95 96#if defined(__LP64__) 97#define MASK 0x7ffffffffffffULL 98#else 99#define MASK 0xffffffffULL 100#endif 101#define PARALLEL 64 102#define RUNTIME (5 * 60) 103#define SYNC 0 104 105static int fd; 106 107static void * 108t1(void *data __unused) 109{ 110 off_t offset; 111 time_t start; 112 113 start = time(NULL); 114 while (time(NULL) - start < 30) { 115 offset = arc4random(); 116 offset = (offset << 32) | arc4random(); 117 offset &= MASK; 118 if (lseek(fd, offset, SEEK_SET) == -1) 119 err(1, "lseek(%jd)", offset); 120 if (write(fd, "a", 1) != 1) 121 err(1, "write"); 122 if (fsync(fd) == -1) 123 err(1, "fsync"); 124 usleep(100); 125 } 126 return (NULL); 127} 128static void * 129t2(void *data __unused) 130{ 131 off_t offset, old; 132 time_t start; 133 void *p; 134 char *c; 135 136 old = 0; 137 start = time(NULL); 138 while (time(NULL) - start < 30) { 139 if (old != 0) 140 munmap(p, old); 141 offset = arc4random(); 142 offset = (offset << 32) | arc4random(); 143 offset &= MASK; 144 if (ftruncate(fd, offset) == -1) 145 err(1, "ftruncate(%jd)", offset); 146 write(fd, "b", 1); 147 p = mmap(NULL, offset, PROT_READ | PROT_WRITE, MAP_SHARED, 148 fd, 0); 149 if (p == MAP_FAILED) 150 old = 0; 151 else { 152 old = offset; 153 c = p; 154 c[offset / 2] = 1; 155 if (offset > 0) 156 c[offset - 1] = 2; 157 } 158 usleep(20000); 159 } 160 return (NULL); 161} 162 163static void 164test(void) 165{ 166 pthread_t tid[2]; 167 int r; 168 char file[80]; 169 170 atomic_add_int(&share[SYNC], 1); 171 while (share[SYNC] != PARALLEL) 172 ; 173 174 snprintf(file, sizeof(file), "file.%d", getpid()); 175 if ((fd = open(file, O_RDWR | O_CREAT, DEFFILEMODE)) == -1) 176 err(1, "open(%s)", file); 177 178 if ((r = pthread_create(&tid[0], NULL, t1, NULL)) != 0) 179 errc(1, r, "pthread_create"); 180 if ((r = pthread_create(&tid[1], NULL, t2, NULL)) != 0) 181 errc(1, r, "pthread_create"); 182 183 if ((r = pthread_join(tid[0], NULL)) != 0) 184 errc(1, r, "pthread_join"); 185 if ((r = pthread_join(tid[1], NULL)) != 0) 186 errc(1, r, "pthread_join"); 187 close(fd); 188 unlink(file); 189 190 _exit(0); 191} 192 193int 194main(void) 195{ 196 pid_t pids[PARALLEL]; 197 size_t len; 198 time_t start; 199 int e, i, status; 200 201 e = 0; 202 len = PAGE_SIZE; 203 if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, 204 MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) 205 err(1, "mmap"); 206 207 start = time(NULL); 208 while ((time(NULL) - start) < RUNTIME && e == 0) { 209 share[SYNC] = 0; 210 for (i = 0; i < PARALLEL; i++) { 211 if ((pids[i] = fork()) == 0) 212 test(); 213 if (pids[i] == -1) 214 err(1, "fork()"); 215 } 216 for (i = 0; i < PARALLEL; i++) { 217 if (waitpid(pids[i], &status, 0) == -1) 218 err(1, "waitpid(%d)", pids[i]); 219 if (status != 0) { 220 if (WIFSIGNALED(status)) 221 fprintf(stderr, 222 "pid %d exit signal %d\n", 223 pids[i], WTERMSIG(status)); 224 } 225 e += status == 0 ? 0 : 1; 226 } 227 } 228 229 return (e); 230} 231