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/*
8cb74972a66bde0af7b1a957d01e0095b82a8b91Jonathan Haslam * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
9512fe850e98fdd448c638ca63fdd92a8a510255ahl * Use is subject to license terms.
9512fe850e98fdd448c638ca63fdd92a8a510255ahl */
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>
73427c57f824c3ec3b396181b163f37d50c5b3b1ahl#include <dtrace.h>
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
4fe01614e64281d82c5a22f0050e55f1e0bdbdaerafint
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
8cb74972a66bde0af7b1a957d01e0095b82a8b91Jonathan Haslam if (argc < 2)
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
73427c57f824c3ec3b396181b163f37d50c5b3b1ahl dof = dtrace_dof_create(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 }
4fe01614e64281d82c5a22f0050e55f1e0bdbdaeraf
4fe01614e64281d82c5a22f0050e55f1e0bdbdaeraf /* NOTREACHED */
4fe01614e64281d82c5a22f0050e55f1e0bdbdaeraf return (0);
9512fe850e98fdd448c638ca63fdd92a8a510255ahl}