xref: /openbsd-src/regress/sys/kern/ptrace/ptrace.c (revision 6e3bbdbc7ca6fb202c4c93125fdee5dce85a6c41)
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