1 /*
2  *             COPYRIGHT (c) 1990 BY             *
3  *  GEORGE J. CARRETTE, CONCORD, MASSACHUSETTS.  *
4  *             ALL RIGHTS RESERVED               *
5 
6 Permission to use, copy, modify, distribute and sell this software
7 and its documentation for any purpose and without fee is hereby
8 granted, provided that the above copyright notice appear in all copies
9 and that both that copyright notice and this permission notice appear
10 in supporting documentation, and that the name of the author
11 not be used in advertising or publicity pertaining to distribution
12 of the software without specific, written prior permission.
13 
14 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16 HE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20 SOFTWARE.
21 
22 This code is based on crashme.c
23 
24 */
25 
26 #include <sys/types.h>
27 #include <sys/mman.h>
28 #include <sys/param.h>
29 #include <sys/resource.h>
30 #include <sys/time.h>
31 #include <err.h>
32 #include <signal.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <sys/wait.h>
36 #include <unistd.h>
37 
38 #include "stress.h"
39 
40 static pid_t pid;
41 static int failsafe;
42 
43 static int
44 tobemangled(void) {
45 	volatile int i, j;
46 
47 	j = 2;
48 	for (i = 0; i < 100; i++)
49 		j = j + 3;
50 	j = j / 2;
51 
52 	return (j);
53 }
54 
55 static void
56 mangle(void) {	/* Change one byte in the code */
57 	int i;
58 	char *p = (void *)tobemangled;
59 
60 	i = arc4random() % 50;
61 	p[i] = arc4random() & 0xff;
62 }
63 
64 static void
65 hand(int i __unused) {	/* handler */
66 	_exit(1);
67 }
68 
69 static void
70 ahand(int i __unused) {	/* alarm handler */
71 	if (pid != 0) {
72 		kill(pid, SIGKILL);
73 	}
74 	_exit(EXIT_SUCCESS);
75 }
76 
77 int
78 setup(int nb __unused)
79 {
80 	return (0);
81 }
82 
83 void
84 cleanup(void)
85 {
86 }
87 
88 int
89 test(void)
90 {
91 	void *st;
92 	struct rlimit rl;
93 
94 	if (failsafe)
95 		return (0);
96 
97 	while (done_testing == 0) {
98 		signal(SIGALRM, ahand);
99 		alarm(3);
100 		if ((pid = fork()) == 0) {
101 			rl.rlim_max = rl.rlim_cur = 0;
102 			if (setrlimit(RLIMIT_CORE, &rl) == -1)
103 				warn("setrlimit");
104 			st = (void *)trunc_page((unsigned long)tobemangled);
105 			if (mprotect(st, PAGE_SIZE, PROT_WRITE | PROT_READ |
106 			    PROT_EXEC) == -1)
107 				err(1, "mprotect()");
108 
109 			signal(SIGALRM, hand);
110 			signal(SIGILL,  hand);
111 			signal(SIGFPE,  hand);
112 			signal(SIGSEGV, hand);
113 			signal(SIGBUS,  hand);
114 			signal(SIGURG,  hand);
115 			signal(SIGSYS,  hand);
116 			signal(SIGTRAP, hand);
117 
118 			mangle();
119 			failsafe = 1;
120 			(void)tobemangled();
121 
122 			_exit(EXIT_SUCCESS);
123 
124 		} else if (pid > 0) {
125 			if (waitpid(pid, NULL, 0) == -1)
126 				warn("waitpid(%d)", pid);
127 			alarm(0);
128 		} else
129 			err(1, "fork(), %s:%d",  __FILE__, __LINE__);
130 	}
131 
132 	return (0);
133 }
134