]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - cddl/contrib/opensolaris/cmd/dtrace/test/cmd/baddof/baddof.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / cddl / contrib / opensolaris / cmd / dtrace / test / cmd / baddof / baddof.c
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 <math.h>
36 #include <dtrace.h>
37
38 void
39 fatal(char *fmt, ...)
40 {
41         va_list ap;
42
43         va_start(ap, fmt);
44
45         fprintf(stderr, "%s: ", "baddof");
46         vfprintf(stderr, fmt, ap);
47
48         if (fmt[strlen(fmt) - 1] != '\n')
49                 fprintf(stderr, ": %s\n", strerror(errno));
50
51         exit(1);
52 }
53
54 #define LEAP_DISTANCE           20
55
56 void
57 corrupt(int fd, unsigned char *buf, int len)
58 {
59         static int ttl, valid;
60         int bit, i;
61         unsigned char saved;
62         int val[LEAP_DISTANCE], pos[LEAP_DISTANCE];
63         int new, rv;
64
65 again:
66         printf("valid DOF #%d\n", valid++);
67
68         /*
69          * We are going iterate through, flipping one bit and attempting
70          * to enable.
71          */
72         for (bit = 0; bit < len * 8; bit++) {
73                 saved = buf[bit / 8];
74                 buf[bit / 8] ^= (1 << (bit % 8));
75
76                 if ((bit % 100) == 0)
77                         printf("%d\n", bit);
78
79                 if ((rv = ioctl(fd, DTRACEIOC_ENABLE, buf)) == -1) {
80                         /*
81                          * That failed -- restore the bit and drive on.
82                          */
83                         buf[bit / 8] = saved;
84                         continue;
85                 }
86
87                 /*
88                  * That worked -- and it may have enabled probes.  To keep
89                  * enabled probes down to a reasonable level, we'll close
90                  * and reopen pseudodevice if we have more than 10,000
91                  * probes enabled.
92                  */
93                 ttl += rv;
94
95                 if (ttl < 10000) {
96                         buf[bit / 8] = saved;
97                         continue;
98                 }
99
100                 printf("enabled %d probes; resetting device.\n", ttl);
101                 close(fd);
102
103                 new = open("/devices/pseudo/dtrace@0:dtrace", O_RDWR);
104
105                 if (new == -1)
106                         fatal("couldn't open DTrace pseudo device");
107
108                 if (new != fd) {
109                         dup2(new, fd);
110                         close(new);
111                 }
112
113                 ttl = 0;
114                 buf[bit / 8] = saved;
115         }
116
117         for (;;) {
118                 /*
119                  * Now we want to get as many bits away as possible.  We flip
120                  * bits randomly -- getting as far away as we can until we don't
121                  * seem to be making any progress.
122                  */
123                 for (i = 0; i < LEAP_DISTANCE; i++) {
124                         /*
125                          * Pick a random bit and corrupt it.
126                          */
127                         bit = lrand48() % (len * 8);
128
129                         val[i] = buf[bit / 8];
130                         pos[i] = bit / 8;
131                         buf[bit / 8] ^= (1 << (bit % 8));
132                 }
133
134                 /*
135                  * Let's see if that managed to get us valid DOF...
136                  */
137                 if ((rv = ioctl(fd, DTRACEIOC_ENABLE, buf)) > 0) {
138                         /*
139                          * Success!  This will be our new base for valid DOF.
140                          */
141                         ttl += rv;
142                         goto again;
143                 }
144
145                 /*
146                  * No luck -- we'll restore those bits and try flipping a
147                  * different set.  Note that this must be done in reverse
148                  * order...
149                  */
150                 for (i = LEAP_DISTANCE - 1; i >= 0; i--)
151                         buf[pos[i]] = val[i];
152         }
153 }
154
155 int
156 main(int argc, char **argv)
157 {
158         char *filename = argv[1];
159         dtrace_hdl_t *dtp;
160         dtrace_prog_t *pgp;
161         int err, fd, len;
162         FILE *fp;
163         unsigned char *dof, *copy;
164
165         if (argc < 1)
166                 fatal("expected D script as argument\n");
167
168         if ((fp = fopen(filename, "r")) == NULL)
169                 fatal("couldn't open %s", filename);
170
171         /*
172          * First, we need to compile our provided D into DOF.
173          */
174         if ((dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) {
175                 fatal("cannot open dtrace library: %s\n",
176                     dtrace_errmsg(NULL, err));
177         }
178
179         pgp = dtrace_program_fcompile(dtp, fp, 0, 0, NULL);
180         fclose(fp);
181
182         if (pgp == NULL) {
183                 fatal("failed to compile script %s: %s\n", filename,
184                     dtrace_errmsg(dtp, dtrace_errno(dtp)));
185         }
186
187         dof = dtrace_dof_create(dtp, pgp, 0);
188         len = ((dof_hdr_t *)dof)->dofh_loadsz;
189
190         if ((copy = malloc(len)) == NULL)
191                 fatal("could not allocate copy of %d bytes", len);
192
193         for (;;) {
194                 bcopy(dof, copy, len);
195                 /*
196                  * Open another instance of the dtrace device.
197                  */
198                 fd = open("/devices/pseudo/dtrace@0:dtrace", O_RDWR);
199
200                 if (fd == -1)
201                         fatal("couldn't open DTrace pseudo device");
202
203                 corrupt(fd, copy, len);
204                 close(fd);
205         }
206
207         /* NOTREACHED */
208         return (0);
209 }