]> git.saurik.com Git - apple/xnu.git/blob - tools/tests/unit_tests/ptrace_tests_10767133_src/ptrace_tests_10767133.c
c863c03d18caa0a449ddb6e4bfa5b2d57a92317d
[apple/xnu.git] / tools / tests / unit_tests / ptrace_tests_10767133_src / ptrace_tests_10767133.c
1 /*
2 * File: ptrace_tests_10767133.c
3 * Test Description: Testing different functions of the ptrace call.
4 * Radar: <rdar://problem/10767133>
5 * compile command: cc -o ../BUILD/ptrace_tests_10767133 ptrace_tests_10767133.c
6 */
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <errno.h>
10 #include <string.h>
11 #include <assert.h>
12 #include <stdlib.h>
13 #include <sys/types.h>
14 #include <sys/ptrace.h>
15 #include <signal.h>
16 #include <sys/wait.h>
17
18 #define assert_condition(condition, exit_status, cause) \
19 if (!(condition)) { \
20 printf("[FAILED] %s:%s at %d error: %s \n", "test_10767133", __func__ , __LINE__, cause ); \
21 if (errno) \
22 perror(cause); \
23 exit(exit_status); \
24 } \
25
26 #define log_message(msg) \
27 printf("%s:%d -> %s \n", __func__, __LINE__, msg);
28
29
30 typedef int * pipe_t;
31
32 ssize_t pipe_read_data(pipe_t p, void *dest_buf, int size)
33 {
34 int fd = p[0];
35 int retval = read(fd, dest_buf, size);
36 if (retval == -1) {
37 printf("Error reading from buffer. ");
38 perror("pipe_read");
39 }
40 return retval;
41 }
42
43 ssize_t pipe_write_data(pipe_t p, void *src_buf, int size)
44 {
45 int fd = p[1];
46 int retval = write(fd, src_buf, size);
47 if (retval == -1) {
48 printf("Error writing to buffer. ");
49 perror("pipe_write");
50 }
51 return retval;
52 }
53
54
55
56 void test_ptrace_deny_tace_sigexc();
57 void test_ptrace_attach_detach();
58 void test_ptrace_step_kill();
59
60 int main(){
61 int retval =0;
62 log_message(" Testing for PT_FORCEQUOTA. it should return EPERM for non root program. ");
63 errno=0;
64 retval = ptrace(PT_FORCEQUOTA, getpid(), NULL, 0);
65 assert_condition( (retval == -1 && errno == EPERM), -1, "PT_FORCEQUOTA");
66
67 log_message(" Testing to PT_DENY_ATTACH. should return successfully as nobody is tracing me.")
68 retval = ptrace(PT_DENY_ATTACH, getpid(), NULL, 0);
69 assert_condition (retval == 0 , -2, "PR_DENY_ATTACH");
70 test_ptrace_deny_tace_sigexc();
71 test_ptrace_attach_detach();
72 test_ptrace_step_kill();
73 success:
74 printf("[PASSED] Test test_10767133 passed. \n");
75 return 0;
76 fail:
77 printf("[FAILED] Test test_10767133 failed. \n");
78 return -1;
79 }
80
81 void test_ptrace_step_kill(){
82 int retval = 0, status=1;
83 int parentpipe[2], childpipe[2], data;
84 enum data_state { begin, finished_child_loop, finished_parent_detach };
85 retval = pipe(childpipe);
86 assert_condition(retval == 0, -1, "Pipe create");
87 retval = pipe(parentpipe);
88 assert_condition(retval == 0, -1, "Pipe create");
89 int childpid = fork();
90 assert_condition(childpid >=0, -1, "fork failed");
91
92 if (childpid == 0){ /* child */
93 pipe_read_data(parentpipe, &data, sizeof(data));
94 assert_condition(data == begin, -1, "child: parent not setting begin");
95 pipe_write_data(childpipe, &data, sizeof(data));
96 log_message("child: running the sleep loop");
97 int i = 5;
98 log_message("child: sleep loop");
99 while (i-- > 0){
100 sleep(1);
101 printf(".z.\n");
102 }
103 data = finished_child_loop;
104 log_message("child: finished sleep loop");
105 pipe_write_data(childpipe, &data, sizeof(data));
106 pipe_read_data(parentpipe, &data, sizeof(data));
107 assert_condition(data == finished_parent_detach, -1, "child: parent not done with detach");
108 i = 5;
109 log_message("child: sleep loop 2");
110 while (i-- > 0){
111 sleep(1);
112 printf(".Z.\n");
113 }
114 exit(57);
115 }else{ /* parent */
116 data = begin;
117 pipe_write_data(parentpipe, &data, sizeof(data));
118 data = getpid();
119 pipe_read_data(childpipe, &data, sizeof(data));
120 assert_condition(data == begin, -1, "child is not ready with TRACE_ME setup");
121 printf("parent: attaching to child with pid %d \n", childpid);
122 retval = ptrace(PT_ATTACH, childpid, NULL, 0);
123 assert_condition(retval == 0, -1, "parent: failed to attach to child");
124 sleep(2);
125 log_message("parent: attached to child. Now PT_STEP through it");
126 retval = ptrace(PT_STEP, childpid, (caddr_t)1, 0);
127 assert_condition(retval == 0, -1, "parent: failed to continue the child");
128 sleep(2);
129 retval = ptrace(PT_STEP, childpid, (caddr_t)1, 0);
130 assert_condition(retval == 0, -1, "parent: failed to continue the child");
131 log_message("parent: issuing PT_KILL to child ");
132 sleep(2);
133 retval = ptrace(PT_KILL, childpid, NULL, 0);
134 assert_condition(retval == 0, -1, "parent: failed to PT_KILL the child");
135 data = finished_parent_detach;
136 pipe_write_data(parentpipe, &data, sizeof(data));
137 waitpid(childpid,&status,0);
138 assert_condition(status != 57, -1, "child has exited successfully. It should have died with signal 9");
139 assert_condition(status == 9, -1, "child has exited unexpectedly. Should have died with signal 9");
140 }
141
142 }
143
144 void test_ptrace_attach_detach(){
145 int retval = 0, status=1;
146 int parentpipe[2], childpipe[2], data;
147 enum data_state { begin, finished_child_loop, finished_parent_detach };
148 retval = pipe(childpipe);
149 assert_condition(retval == 0, -1, "Pipe create");
150 retval = pipe(parentpipe);
151 assert_condition(retval == 0, -1, "Pipe create");
152 int childpid = fork();
153 assert_condition(childpid >=0, -1, "fork failed");
154
155 if (childpid == 0){ /* child */
156 //retval = ptrace(PT_TRACE_ME, getpid(), NULL, 0);
157 //assert_condition(retval == 0, -1, "PT_TRACE_ME failed");
158 pipe_read_data(parentpipe, &data, sizeof(data));
159 assert_condition(data == begin, -1, "child: parent not setting begin");
160 pipe_write_data(childpipe, &data, sizeof(data));
161 log_message("child: running the sleep loop");
162 int i = 5;
163 log_message("child: sleep looping");
164 while (i-- > 0){
165 sleep(1);
166 printf(".z.\n");
167 }
168 data = finished_child_loop;
169 log_message("child: finished sleep loop");
170 pipe_write_data(childpipe, &data, sizeof(data));
171 pipe_read_data(parentpipe, &data, sizeof(data));
172 assert_condition(data == finished_parent_detach, -1, "child: parent not done with detach");
173 i = 5;
174 log_message("child sleep looping too");
175 while (i-- > 0){
176 sleep(1);
177 printf(".Z.\n");
178 }
179 exit(0);
180 }else{ /* parent */
181 data = begin;
182 pipe_write_data(parentpipe, &data, sizeof(data));
183 data = getpid();
184 pipe_read_data(childpipe, &data, sizeof(data));
185 assert_condition(data == begin, -1, "child is not ready with TRACE_ME setup");
186 printf("parent: attaching to child with pid %d \n", childpid);
187 retval = ptrace(PT_ATTACH, childpid, NULL, 0);
188 assert_condition(retval == 0, -1, "parent: failed to attach to child");
189 sleep(2);
190 log_message("parent: attached to child. Now continuing it");
191 retval = ptrace(PT_CONTINUE, childpid, (caddr_t)1, 0);
192 assert_condition(retval == 0, -1, "parent: failed to continue the child");
193
194 pipe_read_data(childpipe, &data, sizeof(data));
195 assert_condition(data == finished_child_loop, -1, "parent: child has not finished while loop");
196
197 retval = kill(childpid, SIGSTOP);
198 assert_condition(retval == 0, -1, "parent: failed to SIGSTOP child");
199 sleep(2);
200
201 log_message("parent: child has finished loop. Now detaching the child");
202 retval = ptrace(PT_DETACH, childpid, NULL, 0);
203 assert_condition(retval == 0, -1, "parent: failed to detach");
204
205 data = finished_parent_detach;
206 pipe_write_data(parentpipe, &data, sizeof(data));
207 waitpid(childpid,&status,0);
208 assert_condition(status == 0, -1, "child has exited unexpectedly");
209 }
210 }
211
212
213 void test_ptrace_deny_tace_sigexc(){
214 enum ptrace_state { begin,denied_attach, sigexc_tested,trace_me_set, attached, stepped, continued, killed };
215 int retval =0;
216 int childpipe[2],parentpipe[2], data[2];
217 retval = pipe(childpipe);
218 assert_condition( retval == 0, -3, "Pipe create");
219 retval = pipe(parentpipe);
220 assert_condition( retval == 0, -3, "Pipe create");
221
222 data[0] = begin; // parent
223 data[1] = begin; //child
224
225 int childpid = fork();
226 int status = 0;
227 assert_condition(childpid >=0, -4, "fork failed");
228
229 if (childpid == 0){
230 /* child */
231 retval = ptrace(PT_DENY_ATTACH, getpid(), NULL,0);
232 data[1] = denied_attach;
233 pipe_write_data(childpipe, &data[1], sizeof(int));
234 log_message("child: waiting for parent to write something");
235 pipe_read_data(parentpipe, &data[0], sizeof(int));
236 assert_condition(data[0] == begin , -5, "child: parent didnt begin with right state");
237
238 /* waiting for parent to verify that PT_SIGEXC fails since child is not yet traced. */
239
240 pipe_read_data(parentpipe, &data[0], sizeof(int));
241 assert_condition(data[0] == sigexc_tested, -5, " child: parent didnt test for sigexc failure");
242 log_message("child: setting myself to be traced");
243 retval = ptrace(PT_TRACE_ME, getpid(), NULL ,0);
244 assert_condition(retval == 0, -6, "child: failed to setmyself for tracing");
245 data[1]=trace_me_set;
246 pipe_write_data(childpipe, &data[1], sizeof(int));
247 log_message("child: setting signals to be exceptions. PT_SIGEXC");
248 retval = ptrace(PT_SIGEXC, getpid(), NULL, 0);
249 assert_condition(retval == 0, -7, "child: failed to set PT_SIGEXC");
250
251 exit(0);
252
253 }else {
254 /* parent */
255 // get status of child
256 pipe_read_data(childpipe, &data[1], sizeof(int));
257 assert_condition(data[1] == denied_attach, -5, "parent: deny_attach_check");
258 pipe_write_data(parentpipe, &data[0], sizeof(int));
259
260 log_message("parent: testing for failure fo PT_SIGEXC ");
261 retval = ptrace(PT_SIGEXC, childpid, NULL, 0);
262 assert_condition(retval < 0 , -5, "PT_SIGEXC did not fail for untraced child");
263 data[0] = sigexc_tested;
264 pipe_write_data(parentpipe, &data[0], sizeof(int));
265
266 pipe_read_data(childpipe, &data[1], sizeof(int));
267 assert_condition(data[1] == trace_me_set , -7, "parent: child has not set PT_TRACE_ME");
268
269 waitpid(childpid, &status, 0);
270 if ( status != 0){
271 log_message("Child exited with non zero status");
272 }
273 }
274
275 close(childpipe[0]);
276 close(childpipe[1]);
277
278 close(parentpipe[0]);
279 close(parentpipe[1]);
280
281 }