1 /*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 /*
21 * NAME
22 * mkdir04
23 *
24 * DESCRIPTION
25 *
26 * ALGORITHM
27 * Setup:
28 * Setup signal handling.
29 * Pause for SIGUSR1 if option specified.
30 * Create temporary directory.
31 *
32 * Test:
33 * Loop if the proper options are given.
34 * fork the first child
35 * set to be ltpuser1
36 * create a dirctory tstdir1 with 0700 permission
37 * fork the second child
38 * set to ltpuser2
39 * try to create a subdirectory tstdir2 under tstdir1
40 * check the returnvalue, if succeeded (return=0)
41 * Log the errno and Issue a FAIL message.
42 * Otherwise,
43 * Verify the errno
44 * if equals to EACCES,
45 * Issue Pass message.
46 * Otherwise,
47 * Issue Fail message.
48 * Cleanup:
49 * Print errno log and/or timing stats if options given
50 * Delete the temporary directory created.
51 * USAGE
52 * mkdir04 [-c n] [-e] [-f] [-i n] [-I x] [-P x] [-t]
53 * where, -c n : Run n copies concurrently.
54 * -e : Turn on errno logging.
55 * -f : Turn off functionality Testing.
56 * -i n : Execute test n times.
57 * -I x : Execute test for x seconds.
58 * -P x : Pause for x seconds between iterations.
59 * -t : Turn on syscall timing.
60 *
61 * HISTORY
62 * 07/2001 Ported by Wayne Boyer
63 *
64 * RESTRICTIONS
65 * None.
66 *
67 */
68
69 #include <errno.h>
70 #include <string.h>
71 #include <signal.h>
72 #include <sys/stat.h>
73 #include <sys/types.h>
74 #include <fcntl.h>
75 #include <pwd.h>
76 #include <sys/wait.h>
77 #include <unistd.h>
78
79 #include "test.h"
80 #include "safe_macros.h"
81
82 void setup();
83 void cleanup();
84 int fail;
85
86 #define PERMS 0700
87
88 static uid_t nobody_uid, bin_uid;
89
90 char *TCID = "mkdir04";
91 int TST_TOTAL = 1;
92 int fail;
93
94 char tstdir1[100];
95 char tstdir2[100];
96
main(int ac,char ** av)97 int main(int ac, char **av)
98 {
99 int lc;
100 int rval;
101 pid_t pid, pid1;
102 int status;
103
104 /*
105 * parse standard options
106 */
107 tst_parse_opts(ac, av, NULL, NULL);
108
109 /*
110 * perform global setup for test
111 */
112 setup();
113
114 /*
115 * check looping state if -i option given
116 */
117 for (lc = 0; TEST_LOOPING(lc); lc++) {
118
119 tst_count = 0;
120
121 /* Initialize the test directories name */
122 sprintf(tstdir1, "tstdir1.%d", getpid());
123 if ((pid = FORK_OR_VFORK()) < 0) {
124 tst_brkm(TBROK, cleanup, "fork #1 failed");
125 }
126
127 if (pid == 0) { /* first child */
128 rval = setreuid(nobody_uid, nobody_uid);
129 if (rval < 0) {
130 tst_resm(TFAIL | TERRNO, "setreuid failed to "
131 "to set the real uid to %d and "
132 "effective uid to %d",
133 nobody_uid, nobody_uid);
134 exit(1);
135 }
136 /* create the parent directory with 0700 permits */
137 if (mkdir(tstdir1, PERMS) == -1) {
138 tst_resm(TFAIL | TERRNO,
139 "mkdir(%s, %#o) Failed",
140 tstdir1, PERMS);
141 exit(1);
142 }
143 /* create tstdir1 succeeded */
144 exit(0);
145 }
146 wait(&status);
147 if (WEXITSTATUS(status) != 0) {
148 tst_brkm(TFAIL, cleanup,
149 "Test to check mkdir EACCES failed"
150 "in create parent directory");
151 }
152
153 sprintf(tstdir2, "%s/tst", tstdir1);
154
155 if ((pid1 = FORK_OR_VFORK()) < 0) {
156 tst_brkm(TBROK, cleanup, "fork #2 failed");
157 }
158
159 if (pid1 == 0) { /* second child */
160 rval = setreuid(bin_uid, bin_uid);
161 if (rval < 0) {
162 tst_resm(TFAIL | TERRNO, "setreuid failed to "
163 "to set the real uid to %d and "
164 "effective uid to %d",
165 bin_uid, bin_uid);
166 exit(1);
167 }
168 if (mkdir(tstdir2, PERMS) != -1) {
169 tst_resm(TFAIL, "mkdir(%s, %#o) unexpected "
170 "succeeded", tstdir2, PERMS);
171 exit(1);
172 }
173 if (errno != EACCES) {
174 tst_resm(TFAIL, "Expected EACCES got %d",
175 errno);
176 exit(1);
177 }
178 /* PASS */
179 exit(0);
180 }
181 waitpid(pid1, &status, 0);
182 if (WEXITSTATUS(status) == 0) {
183 tst_resm(TPASS, "Test to attempt to creat a directory "
184 "in a directory having no permissions "
185 "SUCCEEDED in setting errno to EACCES");
186 } else {
187 tst_resm(TFAIL, "Test to attempt to creat a directory "
188 "in a directory having no permissions FAILED");
189 cleanup();
190 }
191 }
192
193 /*
194 * cleanup and exit
195 */
196 cleanup();
197 tst_exit();
198
199 }
200
201 /*
202 * setup() - performs all ONE TIME setup for this test.
203 */
setup(void)204 void setup(void)
205 {
206 struct passwd *pw;
207
208 tst_require_root();
209
210 pw = SAFE_GETPWNAM(NULL, "nobody");
211 nobody_uid = pw->pw_uid;
212 #ifndef ANDROID
213 pw = SAFE_GETPWNAM(NULL, "bin");
214 #else
215 // user "bin" does not exist in Android kernel
216 pw = SAFE_GETPWNAM(NULL, "everybody");
217 #endif
218 bin_uid = pw->pw_uid;
219
220 tst_sig(FORK, DEF_HANDLER, cleanup);
221
222 TEST_PAUSE;
223
224 /* Create a temporary directory and make it current. */
225 tst_tmpdir();
226
227 umask(0);
228 }
229
230 /*
231 * cleanup() - performs all ONE TIME cleanup for this test at
232 * completion or premature exit.
233 */
cleanup(void)234 void cleanup(void)
235 {
236
237 /*
238 * Remove the temporary directory.
239 */
240 tst_rmdir();
241
242 /*
243 * Exit with return code appropriate for results.
244 */
245
246 }
247