1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <sys/stat.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <fcntl.h>
31 #include <sys/varargs.h>
32 #include <errno.h>
33 #include <sys/mman.h>
34 #include <sys/wait.h>
35 #include <unistd.h>
36 
37 #define	DTRACEIOC	(('d' << 24) | ('t' << 16) | ('r' << 8))
38 #define	DTRACEIOC_MAX	17
39 
40 void
fatal(char * fmt,...)41 fatal(char *fmt, ...)
42 {
43 	va_list ap;
44 
45 	va_start(ap, fmt);
46 
47 	fprintf(stderr, "%s: ", "badioctl");
48 	vfprintf(stderr, fmt, ap);
49 
50 	if (fmt[strlen(fmt) - 1] != '\n')
51 		fprintf(stderr, ": %s\n", strerror(errno));
52 
53 	exit(1);
54 }
55 
56 void
badioctl(pid_t parent)57 badioctl(pid_t parent)
58 {
59 	int fd = -1, random, ps = sysconf(_SC_PAGESIZE);
60 	int i = 0, seconds;
61 	caddr_t addr;
62 	hrtime_t now, last = 0, end;
63 
64 	if ((random = open("/dev/random", O_RDONLY)) == -1)
65 		fatal("couldn't open /dev/random");
66 
67 	if ((addr = mmap(0, ps, PROT_READ | PROT_WRITE,
68 	    MAP_ANON | MAP_PRIVATE, -1, 0)) == (caddr_t)-1)
69 		fatal("mmap");
70 
71 	for (;;) {
72 		unsigned int ioc;
73 
74 		if ((now = gethrtime()) - last > NANOSEC) {
75 			if (kill(parent, 0) == -1 && errno == ESRCH) {
76 				/*
77 				 * Our parent died.  We will kill ourselves in
78 				 * sympathy.
79 				 */
80 				exit(0);
81 			}
82 
83 			/*
84 			 * Once a second, we'll reopen the device.
85 			 */
86 			if (fd != -1)
87 				close(fd);
88 
89 			fd = open("/devices/pseudo/dtrace@0:dtrace", O_RDONLY);
90 
91 			if (fd == -1)
92 				fatal("couldn't open DTrace pseudo device");
93 
94 			last = now;
95 		}
96 
97 
98 		if ((i++ % 1000) == 0) {
99 			/*
100 			 * Every thousand iterations, change our random gunk.
101 			 */
102 			read(random, addr, ps);
103 		}
104 
105 		read(random, &ioc, sizeof (ioc));
106 		ioc %= DTRACEIOC_MAX;
107 		ioc++;
108 		ioctl(fd, DTRACEIOC | ioc, addr);
109 	}
110 }
111 
112 int
main()113 main()
114 {
115 	pid_t child, parent = getpid();
116 	int status;
117 
118 	for (;;) {
119 		if ((child = fork()) == 0)
120 			badioctl(parent);
121 
122 		while (waitpid(child, &status, WEXITED) != child)
123 			continue;
124 
125 		if (WIFEXITED(status)) {
126 			/*
127 			 * Our child exited by design -- we'll exit with
128 			 * the same status code.
129 			 */
130 			exit(WEXITSTATUS(status));
131 		}
132 
133 		/*
134 		 * Our child died on a signal.  Respawn it.
135 		 */
136 		printf("badioctl: child died on signal %d; respawning.\n",
137 		    WTERMSIG(status));
138 		fflush(stdout);
139 	}
140 
141 	/* NOTREACHED */
142 	return (0);
143 }
144