1 /* $OpenBSD: ptrace.c,v 1.3 2014/01/22 00:36:31 guenther Exp $ */ 2 /* 3 * Copyright (c) 2005 Artur Grabowski <art@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/types.h> 19 #include <sys/ptrace.h> 20 #include <sys/mman.h> 21 #include <sys/wait.h> 22 #include <stdlib.h> 23 #include <stdio.h> 24 #include <string.h> 25 #include <unistd.h> 26 #include <signal.h> 27 #include <errno.h> 28 29 static void 30 usage(void) 31 { 32 fprintf(stderr, "Usage: ptrace [-bdirwI]\n"); 33 exit(1); 34 } 35 36 #define MAGIC "asdfblahblahspam1235432blah" 37 #define MAGIC_I 0x47114217 38 39 int 40 main(int argc, char **argv) 41 { 42 int ch; 43 int bad = 0, i, write, I; 44 pid_t pid; 45 char *m; 46 int ps; 47 int status, req; 48 int ret; 49 50 ps = getpagesize(); 51 52 I = 0; 53 i = 0; 54 write = 0; 55 56 while ((ch = getopt(argc, argv, "bdirwI")) != -1) { 57 switch (ch) { 58 case 'b': 59 bad = 1; 60 break; 61 case 'i': 62 i = 1; 63 break; 64 case 'd': 65 i = 0; 66 break; 67 case 'r': 68 write = 0; 69 break; 70 case 'w': 71 write = 1; 72 break; 73 case 'I': 74 I = 1; 75 break; 76 default: 77 usage(); 78 } 79 } 80 81 m = mmap(0, ps, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0); 82 if (m == MAP_FAILED) 83 err(1, "mmap"); 84 85 if (!write) { 86 if (I) 87 memcpy(m, MAGIC, sizeof(MAGIC)); 88 else 89 *(int *)m = MAGIC_I; 90 } 91 if (bad) 92 if (mprotect(m, ps, PROT_NONE)) 93 err(1, "mprotect"); 94 95 switch ((pid = fork())) { 96 case 0: 97 pause(); 98 _exit(0); 99 case -1: 100 err(1, "fork"); 101 } 102 103 ret = 0; 104 105 if (ptrace(PT_ATTACH, pid, 0, 0) == -1) { 106 warn("ptrace(PT_ATTACH)"); 107 ret = -1; 108 goto out; 109 } 110 111 if (wait(&status) != pid) { 112 warn("wait"); 113 ret = -1; 114 goto out; 115 } 116 117 if (!write) { 118 int i, req; 119 120 if (I) { 121 char foo[1024]; 122 struct ptrace_io_desc piod; 123 124 if (i) 125 piod.piod_op = PIOD_READ_I; 126 else 127 piod.piod_op = PIOD_READ_D; 128 piod.piod_offs = m; 129 piod.piod_addr = &foo; 130 piod.piod_len = sizeof(MAGIC); 131 132 if (ptrace(PT_IO, pid, (caddr_t)&piod, 0) == -1) { 133 warn("ptrace(PT_IO)"); 134 if (errno == EFAULT) 135 ret = 1; 136 else 137 ret = -1; 138 goto out; 139 } 140 141 if (memcmp(foo, MAGIC, sizeof(MAGIC))) { 142 warnx("mismatch %s != %s", foo, MAGIC); 143 ret = 1; 144 goto out; 145 } 146 } else { 147 if (i) 148 req = PT_READ_I; 149 else 150 req = PT_READ_D; 151 152 i = ptrace(req, pid, m, sizeof(i)); 153 if (i != MAGIC_I) { 154 warn("ptrace(%d): %d != %d", req, i, MAGIC_I); 155 ret = 1; 156 goto out; 157 } 158 } 159 } else { 160 errx(1, "lazy bum"); 161 } 162 163 out: 164 if (ret == -1) { 165 /* other errors */ 166 ret = 1; 167 } else if (bad) { 168 if (ret == 0) { 169 warnx("protected memory unprotected"); 170 ret = 1; 171 } else { 172 ret = 0; 173 } 174 } 175 176 kill(pid, SIGKILL); 177 178 return ret; 179 } 180