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