1*6e3bbdbcSguenther /* $OpenBSD: ptrace.c,v 1.5 2017/09/16 02:03:40 guenther Exp $ */
2247d0206Sart /*
3247d0206Sart * Copyright (c) 2005 Artur Grabowski <art@openbsd.org>
4247d0206Sart *
5247d0206Sart * Permission to use, copy, modify, and distribute this software for any
6247d0206Sart * purpose with or without fee is hereby granted, provided that the above
7247d0206Sart * copyright notice and this permission notice appear in all copies.
8247d0206Sart *
9247d0206Sart * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10247d0206Sart * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11247d0206Sart * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12247d0206Sart * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13247d0206Sart * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14247d0206Sart * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15247d0206Sart * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16247d0206Sart */
17247d0206Sart
18247d0206Sart #include <sys/types.h>
19247d0206Sart #include <sys/ptrace.h>
20247d0206Sart #include <sys/mman.h>
21247d0206Sart #include <sys/wait.h>
22247d0206Sart #include <stdlib.h>
23247d0206Sart #include <stdio.h>
2468f97adbSguenther #include <string.h>
25247d0206Sart #include <unistd.h>
26247d0206Sart #include <signal.h>
273c6defdeSart #include <errno.h>
28d7ac586eSguenther #include <err.h>
29247d0206Sart
30247d0206Sart static void
usage(void)31247d0206Sart usage(void)
32247d0206Sart {
33247d0206Sart fprintf(stderr, "Usage: ptrace [-bdirwI]\n");
34247d0206Sart exit(1);
35247d0206Sart }
36247d0206Sart
37247d0206Sart #define MAGIC "asdfblahblahspam1235432blah"
38247d0206Sart #define MAGIC_I 0x47114217
39247d0206Sart
40247d0206Sart int
main(int argc,char ** argv)41247d0206Sart main(int argc, char **argv)
42247d0206Sart {
43247d0206Sart int ch;
44247d0206Sart int bad = 0, i, write, I;
45247d0206Sart pid_t pid;
46247d0206Sart char *m;
47247d0206Sart int ps;
48d7ac586eSguenther int status;
49247d0206Sart int ret;
50247d0206Sart
51247d0206Sart ps = getpagesize();
52247d0206Sart
53247d0206Sart I = 0;
54247d0206Sart i = 0;
55247d0206Sart write = 0;
56247d0206Sart
57247d0206Sart while ((ch = getopt(argc, argv, "bdirwI")) != -1) {
58247d0206Sart switch (ch) {
59247d0206Sart case 'b':
60247d0206Sart bad = 1;
61247d0206Sart break;
62247d0206Sart case 'i':
63247d0206Sart i = 1;
64247d0206Sart break;
65247d0206Sart case 'd':
66247d0206Sart i = 0;
67247d0206Sart break;
68247d0206Sart case 'r':
69247d0206Sart write = 0;
70247d0206Sart break;
71247d0206Sart case 'w':
72247d0206Sart write = 1;
73247d0206Sart break;
74247d0206Sart case 'I':
75247d0206Sart I = 1;
76247d0206Sart break;
77247d0206Sart default:
78247d0206Sart usage();
79247d0206Sart }
80247d0206Sart }
81247d0206Sart
82247d0206Sart m = mmap(0, ps, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);
83247d0206Sart if (m == MAP_FAILED)
84247d0206Sart err(1, "mmap");
85247d0206Sart
86247d0206Sart if (!write) {
87247d0206Sart if (I)
88247d0206Sart memcpy(m, MAGIC, sizeof(MAGIC));
89247d0206Sart else
90247d0206Sart *(int *)m = MAGIC_I;
91247d0206Sart }
92247d0206Sart if (bad)
93247d0206Sart if (mprotect(m, ps, PROT_NONE))
94247d0206Sart err(1, "mprotect");
95247d0206Sart
96247d0206Sart switch ((pid = fork())) {
97247d0206Sart case 0:
98247d0206Sart pause();
99247d0206Sart _exit(0);
100247d0206Sart case -1:
101247d0206Sart err(1, "fork");
102247d0206Sart }
103247d0206Sart
104247d0206Sart ret = 0;
105247d0206Sart
106247d0206Sart if (ptrace(PT_ATTACH, pid, 0, 0) == -1) {
107247d0206Sart warn("ptrace(PT_ATTACH)");
108247d0206Sart ret = -1;
109247d0206Sart goto out;
110247d0206Sart }
111247d0206Sart
112247d0206Sart if (wait(&status) != pid) {
113247d0206Sart warn("wait");
114247d0206Sart ret = -1;
115247d0206Sart goto out;
116247d0206Sart }
117247d0206Sart
118247d0206Sart if (!write) {
119d7ac586eSguenther int req;
120247d0206Sart
121247d0206Sart if (I) {
122247d0206Sart char foo[1024];
123247d0206Sart struct ptrace_io_desc piod;
124247d0206Sart
125247d0206Sart if (i)
126247d0206Sart piod.piod_op = PIOD_READ_I;
127247d0206Sart else
128247d0206Sart piod.piod_op = PIOD_READ_D;
129247d0206Sart piod.piod_offs = m;
130247d0206Sart piod.piod_addr = &foo;
131247d0206Sart piod.piod_len = sizeof(MAGIC);
132247d0206Sart
133247d0206Sart if (ptrace(PT_IO, pid, (caddr_t)&piod, 0) == -1) {
134247d0206Sart warn("ptrace(PT_IO)");
135*6e3bbdbcSguenther if (errno == EFAULT)
1363c6defdeSart ret = 1;
1373c6defdeSart else
138247d0206Sart ret = -1;
139247d0206Sart goto out;
140247d0206Sart }
141247d0206Sart
142247d0206Sart if (memcmp(foo, MAGIC, sizeof(MAGIC))) {
143247d0206Sart warnx("mismatch %s != %s", foo, MAGIC);
144247d0206Sart ret = 1;
145247d0206Sart goto out;
146247d0206Sart }
147247d0206Sart } else {
148247d0206Sart if (i)
149247d0206Sart req = PT_READ_I;
150247d0206Sart else
151247d0206Sart req = PT_READ_D;
152247d0206Sart
153247d0206Sart i = ptrace(req, pid, m, sizeof(i));
154247d0206Sart if (i != MAGIC_I) {
155247d0206Sart warn("ptrace(%d): %d != %d", req, i, MAGIC_I);
156247d0206Sart ret = 1;
157247d0206Sart goto out;
158247d0206Sart }
159247d0206Sart }
160247d0206Sart } else {
161247d0206Sart errx(1, "lazy bum");
162247d0206Sart }
163247d0206Sart
164247d0206Sart out:
165247d0206Sart if (ret == -1) {
166247d0206Sart /* other errors */
167247d0206Sart ret = 1;
168247d0206Sart } else if (bad) {
169247d0206Sart if (ret == 0) {
170247d0206Sart warnx("protected memory unprotected");
171247d0206Sart ret = 1;
172247d0206Sart } else {
173247d0206Sart ret = 0;
174247d0206Sart }
175247d0206Sart }
176247d0206Sart
177247d0206Sart kill(pid, SIGKILL);
178247d0206Sart
179247d0206Sart return ret;
180247d0206Sart }
181