1 /* $OpenBSD: ptrace.c,v 1.5 2017/09/16 02:03:40 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 #include <err.h> 29 30 static void 31 usage(void) 32 { 33 fprintf(stderr, "Usage: ptrace [-bdirwI]\n"); 34 exit(1); 35 } 36 37 #define MAGIC "asdfblahblahspam1235432blah" 38 #define MAGIC_I 0x47114217 39 40 int 41 main(int argc, char **argv) 42 { 43 int ch; 44 int bad = 0, i, write, I; 45 pid_t pid; 46 char *m; 47 int ps; 48 int status; 49 int ret; 50 51 ps = getpagesize(); 52 53 I = 0; 54 i = 0; 55 write = 0; 56 57 while ((ch = getopt(argc, argv, "bdirwI")) != -1) { 58 switch (ch) { 59 case 'b': 60 bad = 1; 61 break; 62 case 'i': 63 i = 1; 64 break; 65 case 'd': 66 i = 0; 67 break; 68 case 'r': 69 write = 0; 70 break; 71 case 'w': 72 write = 1; 73 break; 74 case 'I': 75 I = 1; 76 break; 77 default: 78 usage(); 79 } 80 } 81 82 m = mmap(0, ps, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0); 83 if (m == MAP_FAILED) 84 err(1, "mmap"); 85 86 if (!write) { 87 if (I) 88 memcpy(m, MAGIC, sizeof(MAGIC)); 89 else 90 *(int *)m = MAGIC_I; 91 } 92 if (bad) 93 if (mprotect(m, ps, PROT_NONE)) 94 err(1, "mprotect"); 95 96 switch ((pid = fork())) { 97 case 0: 98 pause(); 99 _exit(0); 100 case -1: 101 err(1, "fork"); 102 } 103 104 ret = 0; 105 106 if (ptrace(PT_ATTACH, pid, 0, 0) == -1) { 107 warn("ptrace(PT_ATTACH)"); 108 ret = -1; 109 goto out; 110 } 111 112 if (wait(&status) != pid) { 113 warn("wait"); 114 ret = -1; 115 goto out; 116 } 117 118 if (!write) { 119 int req; 120 121 if (I) { 122 char foo[1024]; 123 struct ptrace_io_desc piod; 124 125 if (i) 126 piod.piod_op = PIOD_READ_I; 127 else 128 piod.piod_op = PIOD_READ_D; 129 piod.piod_offs = m; 130 piod.piod_addr = &foo; 131 piod.piod_len = sizeof(MAGIC); 132 133 if (ptrace(PT_IO, pid, (caddr_t)&piod, 0) == -1) { 134 warn("ptrace(PT_IO)"); 135 if (errno == EFAULT) 136 ret = 1; 137 else 138 ret = -1; 139 goto out; 140 } 141 142 if (memcmp(foo, MAGIC, sizeof(MAGIC))) { 143 warnx("mismatch %s != %s", foo, MAGIC); 144 ret = 1; 145 goto out; 146 } 147 } else { 148 if (i) 149 req = PT_READ_I; 150 else 151 req = PT_READ_D; 152 153 i = ptrace(req, pid, m, sizeof(i)); 154 if (i != MAGIC_I) { 155 warn("ptrace(%d): %d != %d", req, i, MAGIC_I); 156 ret = 1; 157 goto out; 158 } 159 } 160 } else { 161 errx(1, "lazy bum"); 162 } 163 164 out: 165 if (ret == -1) { 166 /* other errors */ 167 ret = 1; 168 } else if (bad) { 169 if (ret == 0) { 170 warnx("protected memory unprotected"); 171 ret = 1; 172 } else { 173 ret = 0; 174 } 175 } 176 177 kill(pid, SIGKILL); 178 179 return ret; 180 } 181