xref: /dragonfly/test/stress/stress2/misc/fuzz.sh (revision dadd6466)
1#!/bin/sh
2
3#
4# Copyright (c) 2008 Peter Holm <pho@FreeBSD.org>
5# All rights reserved.
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 AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26# SUCH DAMAGE.
27#
28# $FreeBSD$
29#
30
31# Stress test UFS2 file systems by introducing single bit errors in the FS
32# fsck fould fix the FS no matter how damaged, but f.x. this panic has been seen:
33#
34# panic(c0912b65,dfe96000,0,c09e4060,ef48c778,...) at panic+0x14b
35# vm_fault(c1868000,dfe96000,1,0) at vm_fault+0x1e0
36# trap_pfault(ef48c894,0,dfe96000) at trap_pfault+0x137
37# trap(dfe90008,ef480028,c0690028,d0560000,dfe96000,...) at trap+0x341
38# calltrap() at calltrap+0x5
39# --- trap 0xc, eip = 0xc08785a6, esp = 0xef48c8d4, ebp = 0xef48c958 ---
40# generic_bcopy(c81cd570,d0508000,c5ead600,c87b81c0,0,...) at generic_bcopy+0x1a
41# ffs_mount(d0508000,c5ead600,0,c09b0860,c5ecfc3c,...) at ffs_mount+0xa14
42# vfs_domount(c5ead600,cd8c7280,ccb75080,0,...) at vfs_domount+0x687
43# vfs_donmount(c5ead600,0,ef48cc04) at vfs_donmount+0x2ef
44# kernel_mount(c5660960,0,bfbfec86,0,fffffffe,...) at kernel_mount+0x6d
45# ffs_cmount(c5660960,bfbfde50,0,c5ead600,c09b0860,...) at ffs_cmount+0x5d
46# mount(c5ead600,ef48cd04) at mount+0x156
47# syscall(3b,3b,3b,804abcf,bfbfe8e4,...) at syscall+0x22f
48
49
50[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
51
52. ../default.cfg
53
54D=$diskimage
55
56tst() {
57   rm -f $D
58   truncate -s 2M $D
59   mdconfig -a -t vnode -f $D -u $mdstart
60   bsdlabel -w md$mdstart auto
61   newfs -b 8192 -f 1024 -U /dev/md${mdstart}${part} > /dev/null 2>&1
62   mount /dev/md${mdstart}${part} $mntpoint
63   cp /etc/passwd /etc/group /etc/hosts $mntpoint
64   cp -r /usr/include/ufs $mntpoint
65   umount $mntpoint
66
67   for i in `jot 50`; do
68      ./fuzz -n 50 $D
69      if fsck -f -y /dev/md${mdstart}${part} 2>&1 | egrep "^[A-Z]" > /dev/null; then
70         if fsck -f -y /dev/md${mdstart}${part} 2>&1 | egrep "^[A-Z]" > /dev/null; then
71            if fsck -f -y /dev/md${mdstart}${part} 2>&1 | egrep "^[A-Z]" > /dev/null; then
72               echo "fsck is giving up in loop $i!"
73               break
74            fi
75         fi
76      fi
77      sync;sync;sync
78      if mount /dev/md${mdstart}${part} $mntpoint; then
79         ls -l $mntpoint > /dev/null
80         find $mntpoint  -exec dd if={} of=/dev/null bs=1m count=3 \; > /dev/null 2>&1
81         umount $mntpoint
82      else
83         echo "Giving up at loop $i"
84         break
85      fi
86   done
87   mdconfig -d -u ${mdstart}
88   rm -f $D
89}
90
91odir=`pwd`
92dir=/tmp
93
94cd $dir
95sed '1,/^EOF/d' < $odir/$0 > $dir/fuzz.c
96cc -o fuzz -Wall fuzz.c
97rm -f fuzz.c
98
99for j in `jot 10`; do
100   date '+%T'
101   tst
102done
103rm -f fuzz
104
105exit
106
107EOF
108#include <stdio.h>
109#include <stdlib.h>
110#include <unistd.h>
111#include <fcntl.h>
112#include <sys/stat.h>
113#include <err.h>
114
115void
116usage(void)
117{
118	fprintf(stderr, "%s {-n <num|-v} <file>\n", getprogname());
119	exit(1);
120}
121
122long
123random_long(long mi, long ma)
124{
125	return (arc4random()  % (ma - mi + 1) + mi);
126}
127
128int
129main(int argc, char **argv)
130{
131	int ch, fd, i, times = 1, verbose = 0;
132	long pos;
133	unsigned char bit, buf, mask, old;
134	struct stat sb;
135
136	while ((ch = getopt(argc, argv, "n:v")) != -1)
137		switch(ch) {
138		case 'n':	/* Bits to alter */
139			if (sscanf(optarg, "%d", &times) != 1)
140				usage();
141			break;
142		case 'v':	/* verbose flag */
143			verbose += 1;
144			break;
145		default:
146			usage();
147		}
148	argc -= optind;
149	argv += optind;
150
151	if (argc == 0)
152		usage();
153
154
155	if ((fd = open(argv[0], O_RDWR)) == -1)
156		err(1, "open(%s)", argv[0]);
157	if (fstat(fd, &sb) == -1)
158		err(1, "stat(%s)", argv[0]);
159
160	for (i = 0; i < times; i++) {
161		pos = random_long(0, sb.st_size - 1);
162		if (lseek(fd, pos, SEEK_SET) == -1)
163			err(1, "fseek(%d, %ld)", fd, pos);
164		if (read(fd, &buf, 1) != 1)
165			err(1, "read(%d)", fd);
166		bit = random_long(0,7);
167		mask = ~(1 << bit);
168		old = buf;
169		buf = (buf & mask) | (~buf & ~mask);
170		if (verbose > 0)
171			printf("Change %2x to %2x at %4ld by flipping bit %d\n",
172					old, buf, pos, bit);
173		if (lseek(fd, pos, SEEK_SET) == -1)
174			err(1, "fseek(%d, %ld)", fd, pos);
175		if (write(fd, &buf, 1) != 1)
176			err(1, "write(%d)", fd);
177	}
178	close(fd);
179	return (0);
180}
181