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
usage(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
main(int argc,char ** argv)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