baddof.c revision 9512fe850e98fdd448c638ca63fdd92a8a510255
9512fe850e98fdd448c638ca63fdd92a8a510255ahl/*
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * CDDL HEADER START
9512fe850e98fdd448c638ca63fdd92a8a510255ahl *
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * The contents of this file are subject to the terms of the
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * Common Development and Distribution License (the "License").
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * You may not use this file except in compliance with the License.
9512fe850e98fdd448c638ca63fdd92a8a510255ahl *
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * or http://www.opensolaris.org/os/licensing.
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * See the License for the specific language governing permissions
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * and limitations under the License.
9512fe850e98fdd448c638ca63fdd92a8a510255ahl *
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * When distributing Covered Code, include this CDDL HEADER in each
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * If applicable, add the following below this CDDL HEADER, with the
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * fields enclosed by brackets "[]" replaced with your own identifying
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * information: Portions Copyright [yyyy] [name of copyright owner]
9512fe850e98fdd448c638ca63fdd92a8a510255ahl *
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * CDDL HEADER END
9512fe850e98fdd448c638ca63fdd92a8a510255ahl */
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl/*
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * Use is subject to license terms.
9512fe850e98fdd448c638ca63fdd92a8a510255ahl */
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl#pragma ident "%Z%%M% %I% %E% SMI"
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl#include <sys/stat.h>
9512fe850e98fdd448c638ca63fdd92a8a510255ahl#include <stdio.h>
9512fe850e98fdd448c638ca63fdd92a8a510255ahl#include <stdlib.h>
9512fe850e98fdd448c638ca63fdd92a8a510255ahl#include <fcntl.h>
9512fe850e98fdd448c638ca63fdd92a8a510255ahl#include <sys/varargs.h>
9512fe850e98fdd448c638ca63fdd92a8a510255ahl#include <errno.h>
9512fe850e98fdd448c638ca63fdd92a8a510255ahl#include <math.h>
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl#define DTRACE_VERSION 1
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahltypedef struct dtrace_hdl dtrace_hdl_t;
9512fe850e98fdd448c638ca63fdd92a8a510255ahltypedef struct dtrace_prog dtrace_prog_t;
9512fe850e98fdd448c638ca63fdd92a8a510255ahltypedef struct dtrace_vector dtrace_vector_t;
9512fe850e98fdd448c638ca63fdd92a8a510255ahltypedef int64_t dtrace_aggvarid_t;
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl#define DTRACEIOC (('d' << 24) | ('t' << 16) | ('r' << 8))
9512fe850e98fdd448c638ca63fdd92a8a510255ahl#define DTRACEIOC_ENABLE (DTRACEIOC | 6) /* enable probes */
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahlextern dtrace_hdl_t *dtrace_open(int, int, int *);
9512fe850e98fdd448c638ca63fdd92a8a510255ahlextern dtrace_prog_t *dtrace_program_fcompile(dtrace_hdl_t *,
9512fe850e98fdd448c638ca63fdd92a8a510255ahl FILE *, uint_t, int, char *const []);
9512fe850e98fdd448c638ca63fdd92a8a510255ahlextern void *dtrace_program_dof(dtrace_hdl_t *, dtrace_prog_t *, uint_t);
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl#define DOF_ID_SIZE 16 /* total size of dofh_ident[] in bytes */
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahltypedef struct dof_hdr {
9512fe850e98fdd448c638ca63fdd92a8a510255ahl uint8_t dofh_ident[DOF_ID_SIZE]; /* identification bytes (see below) */
9512fe850e98fdd448c638ca63fdd92a8a510255ahl uint32_t dofh_flags; /* file attribute flags (if any) */
9512fe850e98fdd448c638ca63fdd92a8a510255ahl uint32_t dofh_hdrsize; /* size of file header in bytes */
9512fe850e98fdd448c638ca63fdd92a8a510255ahl uint32_t dofh_secsize; /* size of section header in bytes */
9512fe850e98fdd448c638ca63fdd92a8a510255ahl uint32_t dofh_secnum; /* number of section headers */
9512fe850e98fdd448c638ca63fdd92a8a510255ahl uint64_t dofh_secoff; /* file offset of section headers */
9512fe850e98fdd448c638ca63fdd92a8a510255ahl uint64_t dofh_loadsz; /* file size of loadable portion */
9512fe850e98fdd448c638ca63fdd92a8a510255ahl uint64_t dofh_filesz; /* file size of entire DOF file */
9512fe850e98fdd448c638ca63fdd92a8a510255ahl uint64_t dofh_pad; /* reserved for future use */
9512fe850e98fdd448c638ca63fdd92a8a510255ahl} dof_hdr_t;
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahlvoid
9512fe850e98fdd448c638ca63fdd92a8a510255ahlfatal(char *fmt, ...)
9512fe850e98fdd448c638ca63fdd92a8a510255ahl{
9512fe850e98fdd448c638ca63fdd92a8a510255ahl va_list ap;
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl va_start(ap, fmt);
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl fprintf(stderr, "%s: ", "baddof");
9512fe850e98fdd448c638ca63fdd92a8a510255ahl vfprintf(stderr, fmt, ap);
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl if (fmt[strlen(fmt) - 1] != '\n')
9512fe850e98fdd448c638ca63fdd92a8a510255ahl fprintf(stderr, ": %s\n", strerror(errno));
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl exit(1);
9512fe850e98fdd448c638ca63fdd92a8a510255ahl}
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl#define LEAP_DISTANCE 20
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahlvoid
9512fe850e98fdd448c638ca63fdd92a8a510255ahlcorrupt(int fd, unsigned char *buf, int len)
9512fe850e98fdd448c638ca63fdd92a8a510255ahl{
9512fe850e98fdd448c638ca63fdd92a8a510255ahl static int ttl, valid;
9512fe850e98fdd448c638ca63fdd92a8a510255ahl int bit, i;
9512fe850e98fdd448c638ca63fdd92a8a510255ahl unsigned char saved;
9512fe850e98fdd448c638ca63fdd92a8a510255ahl int val[LEAP_DISTANCE], pos[LEAP_DISTANCE];
9512fe850e98fdd448c638ca63fdd92a8a510255ahl int new, rv;
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahlagain:
9512fe850e98fdd448c638ca63fdd92a8a510255ahl printf("valid DOF #%d\n", valid++);
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl /*
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * We are going iterate through, flipping one bit and attempting
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * to enable.
9512fe850e98fdd448c638ca63fdd92a8a510255ahl */
9512fe850e98fdd448c638ca63fdd92a8a510255ahl for (bit = 0; bit < len * 8; bit++) {
9512fe850e98fdd448c638ca63fdd92a8a510255ahl saved = buf[bit / 8];
9512fe850e98fdd448c638ca63fdd92a8a510255ahl buf[bit / 8] ^= (1 << (bit % 8));
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl if ((bit % 100) == 0)
9512fe850e98fdd448c638ca63fdd92a8a510255ahl printf("%d\n", bit);
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl if ((rv = ioctl(fd, DTRACEIOC_ENABLE, buf)) == -1) {
9512fe850e98fdd448c638ca63fdd92a8a510255ahl /*
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * That failed -- restore the bit and drive on.
9512fe850e98fdd448c638ca63fdd92a8a510255ahl */
9512fe850e98fdd448c638ca63fdd92a8a510255ahl buf[bit / 8] = saved;
9512fe850e98fdd448c638ca63fdd92a8a510255ahl continue;
9512fe850e98fdd448c638ca63fdd92a8a510255ahl }
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl /*
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * That worked -- and it may have enabled probes. To keep
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * enabled probes down to a reasonable level, we'll close
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * and reopen pseudodevice if we have more than 10,000
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * probes enabled.
9512fe850e98fdd448c638ca63fdd92a8a510255ahl */
9512fe850e98fdd448c638ca63fdd92a8a510255ahl ttl += rv;
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl if (ttl < 10000) {
9512fe850e98fdd448c638ca63fdd92a8a510255ahl buf[bit / 8] = saved;
9512fe850e98fdd448c638ca63fdd92a8a510255ahl continue;
9512fe850e98fdd448c638ca63fdd92a8a510255ahl }
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl printf("enabled %d probes; resetting device.\n", ttl);
9512fe850e98fdd448c638ca63fdd92a8a510255ahl close(fd);
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl new = open("/devices/pseudo/dtrace@0:dtrace", O_RDWR);
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl if (new == -1)
9512fe850e98fdd448c638ca63fdd92a8a510255ahl fatal("couldn't open DTrace pseudo device");
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl if (new != fd) {
9512fe850e98fdd448c638ca63fdd92a8a510255ahl dup2(new, fd);
9512fe850e98fdd448c638ca63fdd92a8a510255ahl close(new);
9512fe850e98fdd448c638ca63fdd92a8a510255ahl }
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl ttl = 0;
9512fe850e98fdd448c638ca63fdd92a8a510255ahl buf[bit / 8] = saved;
9512fe850e98fdd448c638ca63fdd92a8a510255ahl }
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl for (;;) {
9512fe850e98fdd448c638ca63fdd92a8a510255ahl /*
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * Now we want to get as many bits away as possible. We flip
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * bits randomly -- getting as far away as we can until we don't
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * seem to be making any progress.
9512fe850e98fdd448c638ca63fdd92a8a510255ahl */
9512fe850e98fdd448c638ca63fdd92a8a510255ahl for (i = 0; i < LEAP_DISTANCE; i++) {
9512fe850e98fdd448c638ca63fdd92a8a510255ahl /*
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * Pick a random bit and corrupt it.
9512fe850e98fdd448c638ca63fdd92a8a510255ahl */
9512fe850e98fdd448c638ca63fdd92a8a510255ahl bit = lrand48() % (len * 8);
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl val[i] = buf[bit / 8];
9512fe850e98fdd448c638ca63fdd92a8a510255ahl pos[i] = bit / 8;
9512fe850e98fdd448c638ca63fdd92a8a510255ahl buf[bit / 8] ^= (1 << (bit % 8));
9512fe850e98fdd448c638ca63fdd92a8a510255ahl }
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl /*
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * Let's see if that managed to get us valid DOF...
9512fe850e98fdd448c638ca63fdd92a8a510255ahl */
9512fe850e98fdd448c638ca63fdd92a8a510255ahl if ((rv = ioctl(fd, DTRACEIOC_ENABLE, buf)) > 0) {
9512fe850e98fdd448c638ca63fdd92a8a510255ahl /*
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * Success! This will be our new base for valid DOF.
9512fe850e98fdd448c638ca63fdd92a8a510255ahl */
9512fe850e98fdd448c638ca63fdd92a8a510255ahl ttl += rv;
9512fe850e98fdd448c638ca63fdd92a8a510255ahl goto again;
9512fe850e98fdd448c638ca63fdd92a8a510255ahl }
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl /*
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * No luck -- we'll restore those bits and try flipping a
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * different set. Note that this must be done in reverse
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * order...
9512fe850e98fdd448c638ca63fdd92a8a510255ahl */
9512fe850e98fdd448c638ca63fdd92a8a510255ahl for (i = LEAP_DISTANCE - 1; i >= 0; i--)
9512fe850e98fdd448c638ca63fdd92a8a510255ahl buf[pos[i]] = val[i];
9512fe850e98fdd448c638ca63fdd92a8a510255ahl }
9512fe850e98fdd448c638ca63fdd92a8a510255ahl}
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahlvoid
9512fe850e98fdd448c638ca63fdd92a8a510255ahlmain(int argc, char **argv)
9512fe850e98fdd448c638ca63fdd92a8a510255ahl{
9512fe850e98fdd448c638ca63fdd92a8a510255ahl char *filename = argv[1];
9512fe850e98fdd448c638ca63fdd92a8a510255ahl dtrace_hdl_t *dtp;
9512fe850e98fdd448c638ca63fdd92a8a510255ahl dtrace_prog_t *pgp;
9512fe850e98fdd448c638ca63fdd92a8a510255ahl int err, fd, len;
9512fe850e98fdd448c638ca63fdd92a8a510255ahl FILE *fp;
9512fe850e98fdd448c638ca63fdd92a8a510255ahl unsigned char *dof, *copy;
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl if (argc < 1)
9512fe850e98fdd448c638ca63fdd92a8a510255ahl fatal("expected D script as argument\n");
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl if ((fp = fopen(filename, "r")) == NULL)
9512fe850e98fdd448c638ca63fdd92a8a510255ahl fatal("couldn't open %s", filename);
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl /*
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * First, we need to compile our provided D into DOF.
9512fe850e98fdd448c638ca63fdd92a8a510255ahl */
9512fe850e98fdd448c638ca63fdd92a8a510255ahl if ((dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) {
9512fe850e98fdd448c638ca63fdd92a8a510255ahl fatal("cannot open dtrace library: %s\n",
9512fe850e98fdd448c638ca63fdd92a8a510255ahl dtrace_errmsg(NULL, err));
9512fe850e98fdd448c638ca63fdd92a8a510255ahl }
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl pgp = dtrace_program_fcompile(dtp, fp, 0, 0, NULL);
9512fe850e98fdd448c638ca63fdd92a8a510255ahl fclose(fp);
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl if (pgp == NULL) {
9512fe850e98fdd448c638ca63fdd92a8a510255ahl fatal("failed to compile script %s: %s\n", filename,
9512fe850e98fdd448c638ca63fdd92a8a510255ahl dtrace_errmsg(dtp, dtrace_errno(dtp)));
9512fe850e98fdd448c638ca63fdd92a8a510255ahl }
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl dof = dtrace_program_dof(dtp, pgp, 0);
9512fe850e98fdd448c638ca63fdd92a8a510255ahl len = ((dof_hdr_t *)dof)->dofh_loadsz;
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl if ((copy = malloc(len)) == NULL)
9512fe850e98fdd448c638ca63fdd92a8a510255ahl fatal("could not allocate copy of %d bytes", len);
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl for (;;) {
9512fe850e98fdd448c638ca63fdd92a8a510255ahl bcopy(dof, copy, len);
9512fe850e98fdd448c638ca63fdd92a8a510255ahl /*
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * Open another instance of the dtrace device.
9512fe850e98fdd448c638ca63fdd92a8a510255ahl */
9512fe850e98fdd448c638ca63fdd92a8a510255ahl fd = open("/devices/pseudo/dtrace@0:dtrace", O_RDWR);
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl if (fd == -1)
9512fe850e98fdd448c638ca63fdd92a8a510255ahl fatal("couldn't open DTrace pseudo device");
9512fe850e98fdd448c638ca63fdd92a8a510255ahl
9512fe850e98fdd448c638ca63fdd92a8a510255ahl corrupt(fd, copy, len);
9512fe850e98fdd448c638ca63fdd92a8a510255ahl close(fd);
9512fe850e98fdd448c638ca63fdd92a8a510255ahl }
9512fe850e98fdd448c638ca63fdd92a8a510255ahl}