• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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