1178476Sjb/* 2178476Sjb * CDDL HEADER START 3178476Sjb * 4178476Sjb * The contents of this file are subject to the terms of the 5178476Sjb * Common Development and Distribution License (the "License"). 6178476Sjb * You may not use this file except in compliance with the License. 7178476Sjb * 8178476Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9178476Sjb * or http://www.opensolaris.org/os/licensing. 10178476Sjb * See the License for the specific language governing permissions 11178476Sjb * and limitations under the License. 12178476Sjb * 13178476Sjb * When distributing Covered Code, include this CDDL HEADER in each 14178476Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15178476Sjb * If applicable, add the following below this CDDL HEADER, with the 16178476Sjb * fields enclosed by brackets "[]" replaced with your own identifying 17178476Sjb * information: Portions Copyright [yyyy] [name of copyright owner] 18178476Sjb * 19178476Sjb * CDDL HEADER END 20178476Sjb */ 21178476Sjb 22178476Sjb/* 23210767Srpaulo * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24178476Sjb * Use is subject to license terms. 25178476Sjb */ 26178476Sjb 27178476Sjb#include <sys/stat.h> 28178476Sjb#include <stdio.h> 29178476Sjb#include <stdlib.h> 30178476Sjb#include <fcntl.h> 31178476Sjb#include <sys/varargs.h> 32178476Sjb#include <errno.h> 33178476Sjb#include <math.h> 34178476Sjb#include <dtrace.h> 35178476Sjb 36178476Sjbvoid 37178476Sjbfatal(char *fmt, ...) 38178476Sjb{ 39178476Sjb va_list ap; 40178476Sjb 41178476Sjb va_start(ap, fmt); 42178476Sjb 43178476Sjb fprintf(stderr, "%s: ", "baddof"); 44178476Sjb vfprintf(stderr, fmt, ap); 45178476Sjb 46178476Sjb if (fmt[strlen(fmt) - 1] != '\n') 47178476Sjb fprintf(stderr, ": %s\n", strerror(errno)); 48178476Sjb 49178476Sjb exit(1); 50178476Sjb} 51178476Sjb 52178476Sjb#define LEAP_DISTANCE 20 53178476Sjb 54178476Sjbvoid 55178476Sjbcorrupt(int fd, unsigned char *buf, int len) 56178476Sjb{ 57178476Sjb static int ttl, valid; 58178476Sjb int bit, i; 59178476Sjb unsigned char saved; 60178476Sjb int val[LEAP_DISTANCE], pos[LEAP_DISTANCE]; 61178476Sjb int new, rv; 62178476Sjb 63178476Sjbagain: 64178476Sjb printf("valid DOF #%d\n", valid++); 65178476Sjb 66178476Sjb /* 67178476Sjb * We are going iterate through, flipping one bit and attempting 68178476Sjb * to enable. 69178476Sjb */ 70178476Sjb for (bit = 0; bit < len * 8; bit++) { 71178476Sjb saved = buf[bit / 8]; 72178476Sjb buf[bit / 8] ^= (1 << (bit % 8)); 73178476Sjb 74178476Sjb if ((bit % 100) == 0) 75178476Sjb printf("%d\n", bit); 76178476Sjb 77178476Sjb if ((rv = ioctl(fd, DTRACEIOC_ENABLE, buf)) == -1) { 78178476Sjb /* 79178476Sjb * That failed -- restore the bit and drive on. 80178476Sjb */ 81178476Sjb buf[bit / 8] = saved; 82178476Sjb continue; 83178476Sjb } 84178476Sjb 85178476Sjb /* 86178476Sjb * That worked -- and it may have enabled probes. To keep 87178476Sjb * enabled probes down to a reasonable level, we'll close 88178476Sjb * and reopen pseudodevice if we have more than 10,000 89178476Sjb * probes enabled. 90178476Sjb */ 91178476Sjb ttl += rv; 92178476Sjb 93178476Sjb if (ttl < 10000) { 94178476Sjb buf[bit / 8] = saved; 95178476Sjb continue; 96178476Sjb } 97178476Sjb 98178476Sjb printf("enabled %d probes; resetting device.\n", ttl); 99178476Sjb close(fd); 100178476Sjb 101178476Sjb new = open("/devices/pseudo/dtrace@0:dtrace", O_RDWR); 102178476Sjb 103178476Sjb if (new == -1) 104178476Sjb fatal("couldn't open DTrace pseudo device"); 105178476Sjb 106178476Sjb if (new != fd) { 107178476Sjb dup2(new, fd); 108178476Sjb close(new); 109178476Sjb } 110178476Sjb 111178476Sjb ttl = 0; 112178476Sjb buf[bit / 8] = saved; 113178476Sjb } 114178476Sjb 115178476Sjb for (;;) { 116178476Sjb /* 117178476Sjb * Now we want to get as many bits away as possible. We flip 118178476Sjb * bits randomly -- getting as far away as we can until we don't 119178476Sjb * seem to be making any progress. 120178476Sjb */ 121178476Sjb for (i = 0; i < LEAP_DISTANCE; i++) { 122178476Sjb /* 123178476Sjb * Pick a random bit and corrupt it. 124178476Sjb */ 125178476Sjb bit = lrand48() % (len * 8); 126178476Sjb 127178476Sjb val[i] = buf[bit / 8]; 128178476Sjb pos[i] = bit / 8; 129178476Sjb buf[bit / 8] ^= (1 << (bit % 8)); 130178476Sjb } 131178476Sjb 132178476Sjb /* 133178476Sjb * Let's see if that managed to get us valid DOF... 134178476Sjb */ 135178476Sjb if ((rv = ioctl(fd, DTRACEIOC_ENABLE, buf)) > 0) { 136178476Sjb /* 137178476Sjb * Success! This will be our new base for valid DOF. 138178476Sjb */ 139178476Sjb ttl += rv; 140178476Sjb goto again; 141178476Sjb } 142178476Sjb 143178476Sjb /* 144178476Sjb * No luck -- we'll restore those bits and try flipping a 145178476Sjb * different set. Note that this must be done in reverse 146178476Sjb * order... 147178476Sjb */ 148178476Sjb for (i = LEAP_DISTANCE - 1; i >= 0; i--) 149178476Sjb buf[pos[i]] = val[i]; 150178476Sjb } 151178476Sjb} 152178476Sjb 153178476Sjbint 154178476Sjbmain(int argc, char **argv) 155178476Sjb{ 156178476Sjb char *filename = argv[1]; 157178476Sjb dtrace_hdl_t *dtp; 158178476Sjb dtrace_prog_t *pgp; 159178476Sjb int err, fd, len; 160178476Sjb FILE *fp; 161178476Sjb unsigned char *dof, *copy; 162178476Sjb 163210767Srpaulo if (argc < 2) 164178476Sjb fatal("expected D script as argument\n"); 165178476Sjb 166178476Sjb if ((fp = fopen(filename, "r")) == NULL) 167178476Sjb fatal("couldn't open %s", filename); 168178476Sjb 169178476Sjb /* 170178476Sjb * First, we need to compile our provided D into DOF. 171178476Sjb */ 172178476Sjb if ((dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) { 173178476Sjb fatal("cannot open dtrace library: %s\n", 174178476Sjb dtrace_errmsg(NULL, err)); 175178476Sjb } 176178476Sjb 177178476Sjb pgp = dtrace_program_fcompile(dtp, fp, 0, 0, NULL); 178178476Sjb fclose(fp); 179178476Sjb 180178476Sjb if (pgp == NULL) { 181178476Sjb fatal("failed to compile script %s: %s\n", filename, 182178476Sjb dtrace_errmsg(dtp, dtrace_errno(dtp))); 183178476Sjb } 184178476Sjb 185178476Sjb dof = dtrace_dof_create(dtp, pgp, 0); 186178476Sjb len = ((dof_hdr_t *)dof)->dofh_loadsz; 187178476Sjb 188178476Sjb if ((copy = malloc(len)) == NULL) 189178476Sjb fatal("could not allocate copy of %d bytes", len); 190178476Sjb 191178476Sjb for (;;) { 192178476Sjb bcopy(dof, copy, len); 193178476Sjb /* 194178476Sjb * Open another instance of the dtrace device. 195178476Sjb */ 196178476Sjb fd = open("/devices/pseudo/dtrace@0:dtrace", O_RDWR); 197178476Sjb 198178476Sjb if (fd == -1) 199178476Sjb fatal("couldn't open DTrace pseudo device"); 200178476Sjb 201178476Sjb corrupt(fd, copy, len); 202178476Sjb close(fd); 203178476Sjb } 204178476Sjb 205178476Sjb /* NOTREACHED */ 206178476Sjb return (0); 207178476Sjb} 208