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
main(int ac,char ** av)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
setup(void)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
cleanup(void)174 void cleanup(void)
175 {
176 tst_rmdir();
177 }
178