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*8cb74972SJonathan Haslam * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 249512fe85Sahl * Use is subject to license terms. 259512fe85Sahl */ 269512fe85Sahl 279512fe85Sahl #include <sys/stat.h> 289512fe85Sahl #include <stdio.h> 299512fe85Sahl #include <stdlib.h> 309512fe85Sahl #include <fcntl.h> 319512fe85Sahl #include <sys/varargs.h> 329512fe85Sahl #include <errno.h> 339512fe85Sahl #include <math.h> 3473427c57Sahl #include <dtrace.h> 359512fe85Sahl 369512fe85Sahl void 379512fe85Sahl fatal(char *fmt, ...) 389512fe85Sahl { 399512fe85Sahl va_list ap; 409512fe85Sahl 419512fe85Sahl va_start(ap, fmt); 429512fe85Sahl 439512fe85Sahl fprintf(stderr, "%s: ", "baddof"); 449512fe85Sahl vfprintf(stderr, fmt, ap); 459512fe85Sahl 469512fe85Sahl if (fmt[strlen(fmt) - 1] != '\n') 479512fe85Sahl fprintf(stderr, ": %s\n", strerror(errno)); 489512fe85Sahl 499512fe85Sahl exit(1); 509512fe85Sahl } 519512fe85Sahl 529512fe85Sahl #define LEAP_DISTANCE 20 539512fe85Sahl 549512fe85Sahl void 559512fe85Sahl corrupt(int fd, unsigned char *buf, int len) 569512fe85Sahl { 579512fe85Sahl static int ttl, valid; 589512fe85Sahl int bit, i; 599512fe85Sahl unsigned char saved; 609512fe85Sahl int val[LEAP_DISTANCE], pos[LEAP_DISTANCE]; 619512fe85Sahl int new, rv; 629512fe85Sahl 639512fe85Sahl again: 649512fe85Sahl printf("valid DOF #%d\n", valid++); 659512fe85Sahl 669512fe85Sahl /* 679512fe85Sahl * We are going iterate through, flipping one bit and attempting 689512fe85Sahl * to enable. 699512fe85Sahl */ 709512fe85Sahl for (bit = 0; bit < len * 8; bit++) { 719512fe85Sahl saved = buf[bit / 8]; 729512fe85Sahl buf[bit / 8] ^= (1 << (bit % 8)); 739512fe85Sahl 749512fe85Sahl if ((bit % 100) == 0) 759512fe85Sahl printf("%d\n", bit); 769512fe85Sahl 779512fe85Sahl if ((rv = ioctl(fd, DTRACEIOC_ENABLE, buf)) == -1) { 789512fe85Sahl /* 799512fe85Sahl * That failed -- restore the bit and drive on. 809512fe85Sahl */ 819512fe85Sahl buf[bit / 8] = saved; 829512fe85Sahl continue; 839512fe85Sahl } 849512fe85Sahl 859512fe85Sahl /* 869512fe85Sahl * That worked -- and it may have enabled probes. To keep 879512fe85Sahl * enabled probes down to a reasonable level, we'll close 889512fe85Sahl * and reopen pseudodevice if we have more than 10,000 899512fe85Sahl * probes enabled. 909512fe85Sahl */ 919512fe85Sahl ttl += rv; 929512fe85Sahl 939512fe85Sahl if (ttl < 10000) { 949512fe85Sahl buf[bit / 8] = saved; 959512fe85Sahl continue; 969512fe85Sahl } 979512fe85Sahl 989512fe85Sahl printf("enabled %d probes; resetting device.\n", ttl); 999512fe85Sahl close(fd); 1009512fe85Sahl 1019512fe85Sahl new = open("/devices/pseudo/dtrace@0:dtrace", O_RDWR); 1029512fe85Sahl 1039512fe85Sahl if (new == -1) 1049512fe85Sahl fatal("couldn't open DTrace pseudo device"); 1059512fe85Sahl 1069512fe85Sahl if (new != fd) { 1079512fe85Sahl dup2(new, fd); 1089512fe85Sahl close(new); 1099512fe85Sahl } 1109512fe85Sahl 1119512fe85Sahl ttl = 0; 1129512fe85Sahl buf[bit / 8] = saved; 1139512fe85Sahl } 1149512fe85Sahl 1159512fe85Sahl for (;;) { 1169512fe85Sahl /* 1179512fe85Sahl * Now we want to get as many bits away as possible. We flip 1189512fe85Sahl * bits randomly -- getting as far away as we can until we don't 1199512fe85Sahl * seem to be making any progress. 1209512fe85Sahl */ 1219512fe85Sahl for (i = 0; i < LEAP_DISTANCE; i++) { 1229512fe85Sahl /* 1239512fe85Sahl * Pick a random bit and corrupt it. 1249512fe85Sahl */ 1259512fe85Sahl bit = lrand48() % (len * 8); 1269512fe85Sahl 1279512fe85Sahl val[i] = buf[bit / 8]; 1289512fe85Sahl pos[i] = bit / 8; 1299512fe85Sahl buf[bit / 8] ^= (1 << (bit % 8)); 1309512fe85Sahl } 1319512fe85Sahl 1329512fe85Sahl /* 1339512fe85Sahl * Let's see if that managed to get us valid DOF... 1349512fe85Sahl */ 1359512fe85Sahl if ((rv = ioctl(fd, DTRACEIOC_ENABLE, buf)) > 0) { 1369512fe85Sahl /* 1379512fe85Sahl * Success! This will be our new base for valid DOF. 1389512fe85Sahl */ 1399512fe85Sahl ttl += rv; 1409512fe85Sahl goto again; 1419512fe85Sahl } 1429512fe85Sahl 1439512fe85Sahl /* 1449512fe85Sahl * No luck -- we'll restore those bits and try flipping a 1459512fe85Sahl * different set. Note that this must be done in reverse 1469512fe85Sahl * order... 1479512fe85Sahl */ 1489512fe85Sahl for (i = LEAP_DISTANCE - 1; i >= 0; i--) 1499512fe85Sahl buf[pos[i]] = val[i]; 1509512fe85Sahl } 1519512fe85Sahl } 1529512fe85Sahl 1534fe01614Sraf int 1549512fe85Sahl main(int argc, char **argv) 1559512fe85Sahl { 1569512fe85Sahl char *filename = argv[1]; 1579512fe85Sahl dtrace_hdl_t *dtp; 1589512fe85Sahl dtrace_prog_t *pgp; 1599512fe85Sahl int err, fd, len; 1609512fe85Sahl FILE *fp; 1619512fe85Sahl unsigned char *dof, *copy; 1629512fe85Sahl 163*8cb74972SJonathan Haslam if (argc < 2) 1649512fe85Sahl fatal("expected D script as argument\n"); 1659512fe85Sahl 1669512fe85Sahl if ((fp = fopen(filename, "r")) == NULL) 1679512fe85Sahl fatal("couldn't open %s", filename); 1689512fe85Sahl 1699512fe85Sahl /* 1709512fe85Sahl * First, we need to compile our provided D into DOF. 1719512fe85Sahl */ 1729512fe85Sahl if ((dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) { 1739512fe85Sahl fatal("cannot open dtrace library: %s\n", 1749512fe85Sahl dtrace_errmsg(NULL, err)); 1759512fe85Sahl } 1769512fe85Sahl 1779512fe85Sahl pgp = dtrace_program_fcompile(dtp, fp, 0, 0, NULL); 1789512fe85Sahl fclose(fp); 1799512fe85Sahl 1809512fe85Sahl if (pgp == NULL) { 1819512fe85Sahl fatal("failed to compile script %s: %s\n", filename, 1829512fe85Sahl dtrace_errmsg(dtp, dtrace_errno(dtp))); 1839512fe85Sahl } 1849512fe85Sahl 18573427c57Sahl dof = dtrace_dof_create(dtp, pgp, 0); 1869512fe85Sahl len = ((dof_hdr_t *)dof)->dofh_loadsz; 1879512fe85Sahl 1889512fe85Sahl if ((copy = malloc(len)) == NULL) 1899512fe85Sahl fatal("could not allocate copy of %d bytes", len); 1909512fe85Sahl 1919512fe85Sahl for (;;) { 1929512fe85Sahl bcopy(dof, copy, len); 1939512fe85Sahl /* 1949512fe85Sahl * Open another instance of the dtrace device. 1959512fe85Sahl */ 1969512fe85Sahl fd = open("/devices/pseudo/dtrace@0:dtrace", O_RDWR); 1979512fe85Sahl 1989512fe85Sahl if (fd == -1) 1999512fe85Sahl fatal("couldn't open DTrace pseudo device"); 2009512fe85Sahl 2019512fe85Sahl corrupt(fd, copy, len); 2029512fe85Sahl close(fd); 2039512fe85Sahl } 2044fe01614Sraf 2054fe01614Sraf /* NOTREACHED */ 2064fe01614Sraf return (0); 2079512fe85Sahl } 208