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