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 (at) 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 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 */ 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 */ 214 void cleanup(void) 215 { 216 217 } 218