xref: /illumos-gate/usr/src/cmd/dtrace/test/cmd/baddof/baddof.c (revision 73427c57f824c3ec3b396181b163f37d50c5b3b1)
19512fe85Sahl /*
29512fe85Sahl  * CDDL HEADER START
39512fe85Sahl  *
49512fe85Sahl  * The contents of this file are subject to the terms of the
59512fe85Sahl  * Common Development and Distribution License (the "License").
69512fe85Sahl  * You may not use this file except in compliance with the License.
79512fe85Sahl  *
89512fe85Sahl  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99512fe85Sahl  * or http://www.opensolaris.org/os/licensing.
109512fe85Sahl  * See the License for the specific language governing permissions
119512fe85Sahl  * and limitations under the License.
129512fe85Sahl  *
139512fe85Sahl  * When distributing Covered Code, include this CDDL HEADER in each
149512fe85Sahl  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159512fe85Sahl  * If applicable, add the following below this CDDL HEADER, with the
169512fe85Sahl  * fields enclosed by brackets "[]" replaced with your own identifying
179512fe85Sahl  * information: Portions Copyright [yyyy] [name of copyright owner]
189512fe85Sahl  *
199512fe85Sahl  * CDDL HEADER END
209512fe85Sahl  */
219512fe85Sahl 
229512fe85Sahl /*
23*73427c57Sahl  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
249512fe85Sahl  * Use is subject to license terms.
259512fe85Sahl  */
269512fe85Sahl 
279512fe85Sahl #pragma ident	"%Z%%M%	%I%	%E% SMI"
289512fe85Sahl 
299512fe85Sahl #include <sys/stat.h>
309512fe85Sahl #include <stdio.h>
319512fe85Sahl #include <stdlib.h>
329512fe85Sahl #include <fcntl.h>
339512fe85Sahl #include <sys/varargs.h>
349512fe85Sahl #include <errno.h>
359512fe85Sahl #include <math.h>
36*73427c57Sahl #include <dtrace.h>
379512fe85Sahl 
389512fe85Sahl void
399512fe85Sahl fatal(char *fmt, ...)
409512fe85Sahl {
419512fe85Sahl 	va_list ap;
429512fe85Sahl 
439512fe85Sahl 	va_start(ap, fmt);
449512fe85Sahl 
459512fe85Sahl 	fprintf(stderr, "%s: ", "baddof");
469512fe85Sahl 	vfprintf(stderr, fmt, ap);
479512fe85Sahl 
489512fe85Sahl 	if (fmt[strlen(fmt) - 1] != '\n')
499512fe85Sahl 		fprintf(stderr, ": %s\n", strerror(errno));
509512fe85Sahl 
519512fe85Sahl 	exit(1);
529512fe85Sahl }
539512fe85Sahl 
549512fe85Sahl #define	LEAP_DISTANCE		20
559512fe85Sahl 
569512fe85Sahl void
579512fe85Sahl corrupt(int fd, unsigned char *buf, int len)
589512fe85Sahl {
599512fe85Sahl 	static int ttl, valid;
609512fe85Sahl 	int bit, i;
619512fe85Sahl 	unsigned char saved;
629512fe85Sahl 	int val[LEAP_DISTANCE], pos[LEAP_DISTANCE];
639512fe85Sahl 	int new, rv;
649512fe85Sahl 
659512fe85Sahl again:
669512fe85Sahl 	printf("valid DOF #%d\n", valid++);
679512fe85Sahl 
689512fe85Sahl 	/*
699512fe85Sahl 	 * We are going iterate through, flipping one bit and attempting
709512fe85Sahl 	 * to enable.
719512fe85Sahl 	 */
729512fe85Sahl 	for (bit = 0; bit < len * 8; bit++) {
739512fe85Sahl 		saved = buf[bit / 8];
749512fe85Sahl 		buf[bit / 8] ^= (1 << (bit % 8));
759512fe85Sahl 
769512fe85Sahl 		if ((bit % 100) == 0)
779512fe85Sahl 			printf("%d\n", bit);
789512fe85Sahl 
799512fe85Sahl 		if ((rv = ioctl(fd, DTRACEIOC_ENABLE, buf)) == -1) {
809512fe85Sahl 			/*
819512fe85Sahl 			 * That failed -- restore the bit and drive on.
829512fe85Sahl 			 */
839512fe85Sahl 			buf[bit / 8] = saved;
849512fe85Sahl 			continue;
859512fe85Sahl 		}
869512fe85Sahl 
879512fe85Sahl 		/*
889512fe85Sahl 		 * That worked -- and it may have enabled probes.  To keep
899512fe85Sahl 		 * enabled probes down to a reasonable level, we'll close
909512fe85Sahl 		 * and reopen pseudodevice if we have more than 10,000
919512fe85Sahl 		 * probes enabled.
929512fe85Sahl 		 */
939512fe85Sahl 		ttl += rv;
949512fe85Sahl 
959512fe85Sahl 		if (ttl < 10000) {
969512fe85Sahl 			buf[bit / 8] = saved;
979512fe85Sahl 			continue;
989512fe85Sahl 		}
999512fe85Sahl 
1009512fe85Sahl 		printf("enabled %d probes; resetting device.\n", ttl);
1019512fe85Sahl 		close(fd);
1029512fe85Sahl 
1039512fe85Sahl 		new = open("/devices/pseudo/dtrace@0:dtrace", O_RDWR);
1049512fe85Sahl 
1059512fe85Sahl 		if (new == -1)
1069512fe85Sahl 			fatal("couldn't open DTrace pseudo device");
1079512fe85Sahl 
1089512fe85Sahl 		if (new != fd) {
1099512fe85Sahl 			dup2(new, fd);
1109512fe85Sahl 			close(new);
1119512fe85Sahl 		}
1129512fe85Sahl 
1139512fe85Sahl 		ttl = 0;
1149512fe85Sahl 		buf[bit / 8] = saved;
1159512fe85Sahl 	}
1169512fe85Sahl 
1179512fe85Sahl 	for (;;) {
1189512fe85Sahl 		/*
1199512fe85Sahl 		 * Now we want to get as many bits away as possible.  We flip
1209512fe85Sahl 		 * bits randomly -- getting as far away as we can until we don't
1219512fe85Sahl 		 * seem to be making any progress.
1229512fe85Sahl 		 */
1239512fe85Sahl 		for (i = 0; i < LEAP_DISTANCE; i++) {
1249512fe85Sahl 			/*
1259512fe85Sahl 			 * Pick a random bit and corrupt it.
1269512fe85Sahl 			 */
1279512fe85Sahl 			bit = lrand48() % (len * 8);
1289512fe85Sahl 
1299512fe85Sahl 			val[i] = buf[bit / 8];
1309512fe85Sahl 			pos[i] = bit / 8;
1319512fe85Sahl 			buf[bit / 8] ^= (1 << (bit % 8));
1329512fe85Sahl 		}
1339512fe85Sahl 
1349512fe85Sahl 		/*
1359512fe85Sahl 		 * Let's see if that managed to get us valid DOF...
1369512fe85Sahl 		 */
1379512fe85Sahl 		if ((rv = ioctl(fd, DTRACEIOC_ENABLE, buf)) > 0) {
1389512fe85Sahl 			/*
1399512fe85Sahl 			 * Success!  This will be our new base for valid DOF.
1409512fe85Sahl 			 */
1419512fe85Sahl 			ttl += rv;
1429512fe85Sahl 			goto again;
1439512fe85Sahl 		}
1449512fe85Sahl 
1459512fe85Sahl 		/*
1469512fe85Sahl 		 * No luck -- we'll restore those bits and try flipping a
1479512fe85Sahl 		 * different set.  Note that this must be done in reverse
1489512fe85Sahl 		 * order...
1499512fe85Sahl 		 */
1509512fe85Sahl 		for (i = LEAP_DISTANCE - 1; i >= 0; i--)
1519512fe85Sahl 			buf[pos[i]] = val[i];
1529512fe85Sahl 	}
1539512fe85Sahl }
1549512fe85Sahl 
1559512fe85Sahl void
1569512fe85Sahl main(int argc, char **argv)
1579512fe85Sahl {
1589512fe85Sahl 	char *filename = argv[1];
1599512fe85Sahl 	dtrace_hdl_t *dtp;
1609512fe85Sahl 	dtrace_prog_t *pgp;
1619512fe85Sahl 	int err, fd, len;
1629512fe85Sahl 	FILE *fp;
1639512fe85Sahl 	unsigned char *dof, *copy;
1649512fe85Sahl 
1659512fe85Sahl 	if (argc < 1)
1669512fe85Sahl 		fatal("expected D script as argument\n");
1679512fe85Sahl 
1689512fe85Sahl 	if ((fp = fopen(filename, "r")) == NULL)
1699512fe85Sahl 		fatal("couldn't open %s", filename);
1709512fe85Sahl 
1719512fe85Sahl 	/*
1729512fe85Sahl 	 * First, we need to compile our provided D into DOF.
1739512fe85Sahl 	 */
1749512fe85Sahl 	if ((dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) {
1759512fe85Sahl 		fatal("cannot open dtrace library: %s\n",
1769512fe85Sahl 		    dtrace_errmsg(NULL, err));
1779512fe85Sahl 	}
1789512fe85Sahl 
1799512fe85Sahl 	pgp = dtrace_program_fcompile(dtp, fp, 0, 0, NULL);
1809512fe85Sahl 	fclose(fp);
1819512fe85Sahl 
1829512fe85Sahl 	if (pgp == NULL) {
1839512fe85Sahl 		fatal("failed to compile script %s: %s\n", filename,
1849512fe85Sahl 		    dtrace_errmsg(dtp, dtrace_errno(dtp)));
1859512fe85Sahl 	}
1869512fe85Sahl 
187*73427c57Sahl 	dof = dtrace_dof_create(dtp, pgp, 0);
1889512fe85Sahl 	len = ((dof_hdr_t *)dof)->dofh_loadsz;
1899512fe85Sahl 
1909512fe85Sahl 	if ((copy = malloc(len)) == NULL)
1919512fe85Sahl 		fatal("could not allocate copy of %d bytes", len);
1929512fe85Sahl 
1939512fe85Sahl 	for (;;) {
1949512fe85Sahl 		bcopy(dof, copy, len);
1959512fe85Sahl 		/*
1969512fe85Sahl 		 * Open another instance of the dtrace device.
1979512fe85Sahl 		 */
1989512fe85Sahl 		fd = open("/devices/pseudo/dtrace@0:dtrace", O_RDWR);
1999512fe85Sahl 
2009512fe85Sahl 		if (fd == -1)
2019512fe85Sahl 			fatal("couldn't open DTrace pseudo device");
2029512fe85Sahl 
2039512fe85Sahl 		corrupt(fd, copy, len);
2049512fe85Sahl 		close(fd);
2059512fe85Sahl 	}
2069512fe85Sahl }
207