1 /*
2 * Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * You should have received a copy of the GNU General Public License along
13 * with this program; if not, write the Free Software Foundation, Inc.,
14 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
15 *
16 */
17 /**********************************************************
18 *
19 * TEST IDENTIFIER : ptrace03
20 *
21 * EXECUTED BY : anyone
22 *
23 * TEST TITLE : Tests for error conditions
24 *
25 * TEST CASE TOTAL : 3
26 *
27 * AUTHOR : Saji Kumar.V.R <saji.kumar@wipro.com>
28 *
29 * SIGNALS
30 * Uses SIGUSR1 to pause before test if option set.
31 * (See the parse_opts(3) man page).
32 *
33 * DESCRIPTION
34 * Verifies that
35 * 1) ptrace() returns -1 & sets errno to EPERM while tring to trace
36 * process 1
37 * (This test case will be executed only if the kernel version
38 * is 2.6.25 or below)
39 * 2) ptrace() returns -1 & sets errno to ESRCH if process with
40 * specified pid does not exist
41 * 3) ptrace() returns -1 & sets errno to EPERM if we are trying
42 * to trace a process which is already been traced
43 *
44 * Setup:
45 * Setup signal handling.
46 * Pause for SIGUSR1 if option specified.
47 *
48 * Test:
49 * Loop if the proper options are given.
50 * setup signal handler for SIGUSR2 signal
51 * fork a child
52 *
53 * CHILD:
54 * call ptrace() with proper arguments
55 * if ptrace() failed with expected return value & errno
56 * exit with errno
57 * else
58 * Give proper error message
59 * exit with errno
60 *
61 * PARENT:
62 * Wait for child to finish
63 * if child exits with expected errno
64 * Test Passed
65 * else
66 * Test failed
67 *
68 * Cleanup:
69 * Print errno log and/or timing stats if options given
70 *
71 * USAGE: <for command-line>
72 * ptrace03 [-c n] [-e] [-i n] [-I x] [-P x] [-t] [-h] [-f] [-p]
73 * where, -c n : Run n copies concurrently.
74 * -e : Turn on errno logging.
75 * -h : Show help screen
76 * -f : Turn off functional testing
77 * -i n : Execute test n times.
78 * -I x : Execute test for x seconds.
79 * -p : Pause for SIGUSR1 before starting
80 * -P x : Pause for x seconds between iterations.
81 * -t : Turn on syscall timing.
82 *
83 ****************************************************************/
84
85 #include <errno.h>
86 #include <signal.h>
87 #include <sys/wait.h>
88 #include <pwd.h>
89
90 #include <config.h>
91 #include "ptrace.h"
92
93 #include "test.h"
94
95 static void setup(void);
96 static void cleanup(void);
97
98 char *TCID = "ptrace03";
99
100 static pid_t init_pid = 1;
101 static pid_t unused_pid;
102 static pid_t zero_pid;
103
104 struct test_case_t {
105 enum __ptrace_request request;
106 pid_t *pid;
107 int exp_errno;
108 } test_cases[] = {
109 {
110 PTRACE_ATTACH, &init_pid, EPERM}, {
111 PTRACE_ATTACH, &unused_pid, ESRCH}, {
112 PTRACE_TRACEME, &zero_pid, EPERM},};
113
114 int TST_TOTAL = sizeof(test_cases) / sizeof(test_cases[0]);
115
main(int ac,char ** av)116 int main(int ac, char **av)
117 {
118
119 int lc, i;
120 pid_t child_pid;
121 int status;
122
123 tst_parse_opts(ac, av, NULL, NULL);
124
125 setup();
126
127 for (lc = 0; TEST_LOOPING(lc); lc++) {
128
129 tst_count = 0;
130
131 for (i = 0; i < TST_TOTAL; ++i) {
132
133 /* since Linux 2.6.26, it's allowed to trace init,
134 so just skip this test case */
135 if (i == 0 && tst_kvercmp(2, 6, 25) > 0) {
136 tst_resm(TCONF,
137 "this kernel allows to trace init");
138 continue;
139 }
140
141 /* fork() */
142 switch (child_pid = FORK_OR_VFORK()) {
143
144 case -1:
145 /* fork() failed */
146 tst_resm(TFAIL, "fork() failed");
147 continue;
148
149 case 0:
150 /* Child */
151
152 /* setup for third test case */
153 if (i == 2) {
154 if ((ptrace(PTRACE_TRACEME, 0,
155 NULL, NULL)) == -1) {
156 tst_resm(TWARN, "ptrace()"
157 " falied with errno, %d : %s",
158 errno,
159 strerror(errno));
160 exit(0);
161 }
162 }
163
164 TEST(ptrace(test_cases[i].request,
165 *(test_cases[i].pid), NULL, NULL));
166 if ((TEST_RETURN == -1) && (TEST_ERRNO ==
167 test_cases
168 [i].exp_errno)) {
169 exit(TEST_ERRNO);
170 } else {
171 tst_resm(TWARN | TTERRNO,
172 "ptrace() returned %ld",
173 TEST_RETURN);
174 exit(TEST_ERRNO);
175 }
176
177 default:
178 /* Parent */
179 if ((waitpid(child_pid, &status, 0)) < 0) {
180 tst_resm(TFAIL, "waitpid() failed");
181 continue;
182 }
183 if ((WIFEXITED(status)) &&
184 (WEXITSTATUS(status) ==
185 test_cases[i].exp_errno)) {
186 tst_resm(TPASS, "Test Passed");
187 } else {
188 tst_resm(TFAIL, "Test Failed");
189 }
190 }
191 }
192 }
193
194 /* cleanup and exit */
195 cleanup();
196
197 tst_exit();
198
199 }
200
201 /* setup() - performs all ONE TIME setup for this test */
setup(void)202 void setup(void)
203 {
204 unused_pid = tst_get_unused_pid(cleanup);
205
206 TEST_PAUSE;
207
208 }
209
210 /*
211 *cleanup() - performs all ONE TIME cleanup for this test at
212 * completion or premature exit.
213 */
cleanup(void)214 void cleanup(void)
215 {
216
217 }
218