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 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <sys/stat.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <fcntl.h>
33 #include <sys/varargs.h>
34 #include <errno.h>
35 #include <sys/mman.h>
36 #include <sys/wait.h>
37 #include <unistd.h>
38
39 #define DTRACEIOC (('d' << 24) | ('t' << 16) | ('r' << 8))
40 #define DTRACEIOC_MAX 17
41
42 void
fatal(char * fmt,...)43 fatal(char *fmt, ...)
44 {
45 va_list ap;
46
47 va_start(ap, fmt);
48
49 fprintf(stderr, "%s: ", "badioctl");
50 vfprintf(stderr, fmt, ap);
51
52 if (fmt[strlen(fmt) - 1] != '\n')
53 fprintf(stderr, ": %s\n", strerror(errno));
54
55 exit(1);
56 }
57
58 void
badioctl(pid_t parent)59 badioctl(pid_t parent)
60 {
61 int fd = -1, random, ps = sysconf(_SC_PAGESIZE);
62 int i = 0, seconds;
63 caddr_t addr;
64 hrtime_t now, last = 0, end;
65
66 if ((random = open("/dev/random", O_RDONLY)) == -1)
67 fatal("couldn't open /dev/random");
68
69 if ((addr = mmap(0, ps, PROT_READ | PROT_WRITE,
70 MAP_ANON | MAP_PRIVATE, -1, 0)) == (caddr_t)-1)
71 fatal("mmap");
72
73 for (;;) {
74 unsigned int ioc;
75
76 if ((now = gethrtime()) - last > NANOSEC) {
77 if (kill(parent, 0) == -1 && errno == ESRCH) {
78 /*
79 * Our parent died. We will kill ourselves in
80 * sympathy.
81 */
82 exit(0);
83 }
84
85 /*
86 * Once a second, we'll reopen the device.
87 */
88 if (fd != -1)
89 close(fd);
90
91 fd = open("/devices/pseudo/dtrace@0:dtrace", O_RDONLY);
92
93 if (fd == -1)
94 fatal("couldn't open DTrace pseudo device");
95
96 last = now;
97 }
98
99
100 if ((i++ % 1000) == 0) {
101 /*
102 * Every thousand iterations, change our random gunk.
103 */
104 read(random, addr, ps);
105 }
106
107 read(random, &ioc, sizeof (ioc));
108 ioc %= DTRACEIOC_MAX;
109 ioc++;
110 ioctl(fd, DTRACEIOC | ioc, addr);
111 }
112 }
113
114 int
main()115 main()
116 {
117 pid_t child, parent = getpid();
118 int status;
119
120 for (;;) {
121 if ((child = fork()) == 0)
122 badioctl(parent);
123
124 while (waitpid(child, &status, WEXITED) != child)
125 continue;
126
127 if (WIFEXITED(status)) {
128 /*
129 * Our child exited by design -- we'll exit with
130 * the same status code.
131 */
132 exit(WEXITSTATUS(status));
133 }
134
135 /*
136 * Our child died on a signal. Respawn it.
137 */
138 printf("badioctl: child died on signal %d; respawning.\n",
139 WTERMSIG(status));
140 fflush(stdout);
141 }
142
143 /* NOTREACHED */
144 return (0);
145 }
146