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