1 /* 2 * 3 * Copyright (C) Bull S.A. 2001 4 * Copyright (c) International Business Machines Corp., 2001 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 14 * the GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21 /* 22 * NAME 23 * fchdir03 24 * 25 * DESCRIPTION 26 * Testcase for testing that fchdir(2) sets EACCES errno 27 * 28 * ALGORITHM 29 * 1. create a child process, sets its uid to ltpuser1 30 * 2. this child creates a directory with perm 400, 31 * 3. this child opens the directory and gets a file descriptor 32 * 4. this child attempts to fchdir(2) to the directory created in 2. 33 * and expects to get an EACCES. 34 * 5. finally this child checks the return code, 35 * resets the process ID to root and calls cleanup. 36 * 37 * USAGE: <for command-line> 38 * fchdir03 [-c n] [-e] [-i n] [-I x] [-P x] [-t] 39 * where, -c n : Run n copies concurrently. 40 * -e : Turn on errno logging. 41 * -i n : Execute test n times. 42 * -I x : Execute test for x seconds. 43 * -P x : Pause for x seconds between iterations. 44 * -t : Turn on syscall timing. 45 * 46 * HISTORY 47 * 04/2002 Ported by Jacky Malcles 48 * 49 * RESTRICTIONS 50 * This test must be run as root. 51 */ 52 53 #include <sys/types.h> 54 #include <sys/stat.h> 55 #include <sys/wait.h> 56 #include <errno.h> 57 #include <fcntl.h> 58 #include <pwd.h> 59 #include <stdio.h> 60 #include <string.h> 61 #include <unistd.h> 62 63 #include "test.h" 64 #include "safe_macros.h" 65 66 char *TCID = "fchdir03"; 67 int TST_TOTAL = 1; 68 69 void setup(void); 70 void cleanup(void); 71 72 char good_dir[100]; 73 int fd; 74 75 static uid_t nobody_uid; 76 77 int main(int ac, char **av) 78 { 79 int lc; 80 81 pid_t pid; 82 int status; 83 84 tst_parse_opts(ac, av, NULL, NULL); 85 86 setup(); 87 88 for (lc = 0; TEST_LOOPING(lc); lc++) { 89 tst_count = 0; 90 91 if ((pid = FORK_OR_VFORK()) == -1) 92 tst_brkm(TBROK, cleanup, "fork failed"); 93 94 if (pid == 0) { 95 /* 96 * set the child's ID to ltpuser1 using seteuid() 97 * so that the ID can be changed back after the 98 * TEST call is made. 99 */ 100 if (seteuid(nobody_uid) != 0) { 101 perror("setreuid failed in child #1"); 102 exit(1); 103 } 104 if (mkdir(good_dir, 00400) != 0) { 105 perror("mkdir failed in child #1"); 106 exit(1); 107 } 108 if ((fd = open(good_dir, O_RDONLY)) == -1) { 109 perror("opening directory failed"); 110 } 111 112 TEST(fchdir(fd)); 113 114 if (TEST_RETURN != -1) { 115 printf("Call succeeded unexpectedly\n"); 116 exit(1); 117 } else if (TEST_ERRNO != EACCES) { 118 printf("Expected %d - got %d\n", 119 EACCES, TEST_ERRNO); 120 exit(1); 121 } else 122 printf("Got EACCES as expected\n"); 123 124 /* reset the UID to root */ 125 if (setuid(0) == -1) 126 perror("setuid(0) failed"); 127 128 } else { 129 if (wait(&status) == -1) 130 tst_brkm(TBROK | TERRNO, cleanup, 131 "wait failed"); 132 else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) 133 tst_brkm(TBROK, cleanup, 134 "child exited abnormally (wait status = " 135 "%d", status); 136 else { 137 /* let the child carry on */ 138 exit(0); 139 } 140 } 141 142 if (rmdir(good_dir) == -1) 143 tst_brkm(TBROK, cleanup, "rmdir failed"); 144 145 } 146 cleanup(); 147 148 tst_exit(); 149 } 150 151 void setup(void) 152 { 153 struct passwd *pw; 154 155 char *cur_dir = NULL; 156 157 tst_require_root(); 158 159 pw = SAFE_GETPWNAM(NULL, "nobody"); 160 nobody_uid = pw->pw_uid; 161 162 tst_sig(FORK, DEF_HANDLER, cleanup); 163 164 TEST_PAUSE; 165 166 tst_tmpdir(); 167 168 if ((cur_dir = getcwd(cur_dir, 0)) == NULL) 169 tst_brkm(TBROK | TERRNO, cleanup, "getcwd failed"); 170 171 sprintf(good_dir, "%s.%d", cur_dir, getpid()); 172 } 173 174 void cleanup(void) 175 { 176 tst_rmdir(); 177 } 178