3 * Copyright (c) International Business Machines Corp., 2001
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 * 1) chmod(2) returns -1 and sets errno to EPERM if the effective user id
26 * of process does not match the owner of the file and the process is
28 * 2) chmod(2) returns -1 and sets errno to EACCES if search permission is
29 * denied on a component of the path prefix.
30 * 3) chmod(2) returns -1 and sets errno to EFAULT if pathname points
31 * outside user's accessible address space.
32 * 4) chmod(2) returns -1 and sets errno to ENAMETOOLONG if the pathname
33 * component is too long.
34 * 5) chmod(2) returns -1 and sets errno to ENOTDIR if the directory
35 * component in pathname is not a directory.
36 * 6) chmod(2) returns -1 and sets errno to ENOENT if the specified file
40 * chmod() should fail with return value -1 and set expected errno.
44 * Setup signal handling.
45 * Create temporary directory.
46 * Pause for SIGUSR1 if option specified.
49 * Loop if the proper options are given.
51 * Check return code, if system call failed (return=-1)
52 * if errno set == expected errno
53 * Issue sys call fails with expected return value and errno.
55 * Issue sys call fails with unexpected errno.
57 * Issue sys call returns unexpected value.
60 * Print errno log and/or timing stats if options given
61 * Delete the temporary directory(s)/file(s) created.
63 * Usage: <for command-line>
64 * chmod06 [-c n] [-e] [-f] [-i n] [-I x] [-p x] [-t]
65 * where, -c n : Run n copies concurrently.
66 * -e : Turn on errno logging.
67 * -f : Turn off functionality Testing.
68 * -i n : Execute test n times.
69 * -I x : Execute test for x seconds.
70 * -P x : Pause for x seconds between iterations.
71 * -t : Turn on syscall timing.
74 * 07/2001 Ported by Wayne Boyer
92 #include <sys/types.h>
99 #define MODE_RWX S_IRWXU | S_IRWXG | S_IRWXO
100 #define FILE_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
101 #define DIR_TEMP "testdir_1"
102 #define TEST_FILE1 "tfile_1"
103 #define TEST_FILE2 "testdir_1/tfile_2"
104 #define TEST_FILE3 "t_file/tfile_3"
106 int no_setup(); /* dummy setup function */
107 int setup1(); /* setup function to test chmod for EPERM */
108 int setup2(); /* setup function to test chmod for EACCES */
109 int setup3(); /* setup function to test chmod for ENOTDIR */
110 int longpath_setup(); /* setup function to test chmod for ENAMETOOLONG */
112 char *get_high_address(); /* Function from ltp-Lib */
114 char *test_home
; /* variable to hold TESTHOME env. */
115 char Longpathname
[PATH_MAX
+2];
116 char High_address_node
[64];
118 struct test_case_t
{ /* test case struct. to hold ref. test cond's*/
125 { TEST_FILE1
, "Process is not owner/root", FILE_MODE
, EPERM
, setup1
},
126 { TEST_FILE2
, "No Search permissions to process", FILE_MODE
, EACCES
, setup2
},
127 { High_address_node
, "Address beyond address space", FILE_MODE
, EFAULT
, no_setup
},
128 { (char *)-1, "Negative address", FILE_MODE
, EFAULT
, no_setup
},
129 { Longpathname
, "Pathname too long", FILE_MODE
, ENAMETOOLONG
, longpath_setup
},
130 { "", "Pathname is empty", FILE_MODE
, ENOENT
, no_setup
},
131 { TEST_FILE3
, "Path contains regular file", FILE_MODE
, ENOTDIR
, setup3
},
132 { NULL
, NULL
, 0, 0, no_setup
}
135 char *TCID
="chmod06"; /* Test program identifier. */
136 int TST_TOTAL
= 7; /* Total number of test cases. */
137 extern int Tst_count
; /* Test Case counter for tst_* routines */
138 int exp_enos
[]={EPERM
, EACCES
, EFAULT
, ENAMETOOLONG
, ENOENT
, ENOTDIR
, 0};
142 void setup(); /* Main setup function for the tests */
143 void cleanup(); /* cleanup function for the test */
146 main(int ac
, char **av
)
148 int lc
; /* loop counter */
149 char *msg
; /* message returned from parse_opts */
150 char *file_name
; /* ptr. for file name whose mode is modified*/
151 char *test_desc
; /* test specific error message */
152 int ind
; /* counter to test different test conditions */
153 int mode
; /* creation mode for the node created */
154 char nobody_uid
[] = "nobody";
155 struct passwd
*ltpuser
;
157 /* Parse standard options given to run the test. */
158 msg
= parse_opts(ac
, av
, (option_t
*) NULL
, NULL
);
159 if (msg
!= (char *) NULL
) {
160 tst_brkm(TBROK
, NULL
, "OPTION PARSING ERROR - %s", msg
);
165 * Invoke setup function to call individual test setup functions
166 * to simulate test conditions.
170 /* set the expected errnos... */
171 TEST_EXP_ENOS(exp_enos
);
174 /* Check looping state if -c option given */
175 for (lc
= 0; TEST_LOOPING(lc
); lc
++) {
176 /* Reset Tst_count in case we are looping. */
179 for (ind
= 0; Test_cases
[ind
].desc
!= NULL
; ind
++) {
180 file_name
= Test_cases
[ind
].pathname
;
181 mode
= Test_cases
[ind
].mode
;
182 test_desc
= Test_cases
[ind
].desc
;
184 if (file_name
== High_address_node
) {
185 file_name
= (char *)get_high_address();
188 /* Switch to nobody user for correct error code collection */
189 ltpuser
= getpwnam(nobody_uid
);
190 if (seteuid(ltpuser
->pw_uid
) == -1) {
191 tst_resm(TINFO
, "seteuid failed to "
192 "to set the effective uid to %d",
202 * Call chmod(2) to test different test conditions.
203 * verify that it fails with -1 return value and
204 * sets appropriate errno.
206 TEST(chmod(file_name
, mode
));
208 /* Check return code from chmod(2) */
209 if (TEST_RETURN
!= -1) {
210 tst_resm(TFAIL
, "chmod() returned %d, "
211 "expected -1, errno:%d", TEST_RETURN
,
212 Test_cases
[ind
].exp_errno
);
216 TEST_ERROR_LOG(TEST_ERRNO
);
217 if (TEST_ERRNO
== Test_cases
[ind
].exp_errno
) {
218 tst_resm(TPASS
, "chmod() fails, %s, errno:%d",
219 test_desc
, TEST_ERRNO
);
221 tst_resm(TFAIL
, "chmod() fails, %s, errno:%d, "
222 "expected errno:%d", test_desc
,
223 TEST_ERRNO
, Test_cases
[ind
].exp_errno
);
225 } /* End of TEST CASE LOOPING. */
227 } /* End for TEST_LOOPING */
230 * Invoke cleanup() to delete the test directory/file(s) created
241 * setup(void) - performs all ONE TIME setup for this test.
242 * Exit the test program on receipt of unexpected signals.
243 * Create a temporary directory and change directory to it.
244 * Invoke individual test setup functions according to the order
245 * set in struct. definition.
250 int ind
; /* counter for setup functions */
252 /* Capture unexpected signals */
253 tst_sig(FORK
, DEF_HANDLER
, cleanup
);
255 test_home
= get_current_dir_name();
257 /* Switch to nobody user for correct error code collection */
258 if (geteuid() != 0) {
259 tst_brkm(TBROK
, tst_exit
, "Test must be run as root");
263 /* Pause if that option was specified */
266 /* Make a temp dir and cd to it */
269 bad_addr
= mmap(0, 1, PROT_NONE
,
270 MAP_PRIVATE_EXCEPT_UCLINUX
|MAP_ANONYMOUS
, 0, 0);
271 if (bad_addr
== MAP_FAILED
) {
272 tst_brkm(TBROK
, cleanup
, "mmap failed");
274 Test_cases
[3].pathname
= bad_addr
;
276 /* call individual setup functions */
277 for (ind
= 0; Test_cases
[ind
].desc
!= NULL
; ind
++) {
278 Test_cases
[ind
].setupfunc();
284 * no_setup() - Some test conditions for mknod(2) do not any setup.
285 * Hence, this function just returns 0.
286 * This function simply returns 0.
296 * setup1() - setup function for a test condition for which chmod(2)
297 * returns -1 and sets errno to EPERM.
299 * Create a testfile under temporary directory and invoke setuid to root
300 * program to change the ownership of testfile to that of "ltpuser2" user.
309 /* open/creat a test file and close it */
310 if ((fd
= open(TEST_FILE1
, O_RDWR
|O_CREAT
, 0666)) == -1) {
311 tst_brkm(TBROK
, cleanup
,
312 "open(%s, O_RDWR|O_CREAT, 0666) failed, errno=%d : %s",
313 TEST_FILE1
, errno
, strerror(errno
));
316 if(fchown(fd
, 0, 0)<0)
317 tst_brkm(TBROK
, cleanup
,
318 "Fail to modify %s ownership(s): %s", TEST_FILE1
, strerror(errno
));
320 if (close(fd
) == -1) {
321 tst_brkm(TBROK
, cleanup
,
322 "close(%s) Failed, errno=%d : %s",
323 TEST_FILE1
, errno
, strerror(errno
));
331 * setup2() - setup function for a test condition for which mknod(2)
332 * returns -1 and sets errno to EACCES.
333 * Create a test directory under temporary directory and create a test file
334 * under this directory with mode "0666" permissions.
335 * Modify the mode permissions on test directory such that process will not
336 * have search permissions on test directory.
338 * The function returns 0.
343 int fd
; /* file handle for testfile */
345 /* Creat a test directory and a file under it */
346 if (mkdir(DIR_TEMP
, MODE_RWX
) < 0) {
347 tst_brkm(TBROK
, cleanup
, "mkdir(2) of %s failed", DIR_TEMP
);
350 if ((fd
= open(TEST_FILE2
, O_RDWR
|O_CREAT
, 0666)) == -1) {
351 tst_brkm(TBROK
, cleanup
,
352 "open(%s, O_RDWR|O_CREAT, 0666) failed, errno=%d : %s",
353 TEST_FILE2
, errno
, strerror(errno
));
356 /* Close the testfile created above */
357 if (close(fd
) == -1) {
358 tst_brkm(TBROK
, cleanup
,
359 "close(%s) Failed, errno=%d : %s",
360 TEST_FILE2
, errno
, strerror(errno
));
363 /* Modify mode permissions on test directory */
364 if (chmod(DIR_TEMP
, FILE_MODE
) < 0) {
365 tst_brkm(TBROK
, cleanup
, "chmod(2) of %s failed", DIR_TEMP
);
372 * setup3() - setup function for a test condition for which chmod(2)
373 * returns -1 and sets errno to ENOTDIR.
375 * Create a test file under temporary directory so that test tries to
376 * change mode of a testfile "tfile_3" under "t_file" which happens to be
377 * another regular file.
384 /* Creat a test file under temporary directory and close it */
385 if ((fd
= open("t_file", O_RDWR
|O_CREAT
, MODE_RWX
)) == -1) {
386 tst_brkm(TBROK
, cleanup
,
387 "open(2) on t_file failed, errno=%d : %s",
388 errno
, strerror(errno
));
390 if (close(fd
) == -1) {
391 tst_brkm(TBROK
, cleanup
,
392 "close(t_file) Failed, errno=%d : %s",
393 errno
, strerror(errno
));
400 * longpath_setup() - setup to create a node with a name length exceeding
401 * the MAX. length of PATH_MAX.
402 * This function returns 0.
407 int ind
; /* counter variable */
409 for (ind
= 0; ind
<= (PATH_MAX
+ 1); ind
++) {
410 Longpathname
[ind
] = 'a';
417 * cleanup() - Performs all ONE TIME cleanup for this test at
418 * completion or premature exit.
419 * Print test timing stats and errno log if test executed with options.
420 * Remove temporary directory and sub-directories/files under it
421 * created during setup().
422 * Exit the test program with normal exit code.
428 * print timing stats if that option was specified.
429 * print errno log if that option was specified.
433 /* Restore mode permissions on test directory created in setup2() */
434 if (chmod(DIR_TEMP
, MODE_RWX
) < 0) {
435 tst_brkm(TBROK
, NULL
, "chmod(2) of %s failed", DIR_TEMP
);
438 /* Remove files and temporary directory created */
441 /* exit with return code appropriate for results */
443 } /* End cleanup() */