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) fchown(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) fchown(2) returns -1 and sets errno to EBADF if the file descriptor
29 * of the specified file is not valid.
32 * fchown() should fail with return value -1 and set expected errno.
36 * Setup signal handling.
37 * Create temporary directory.
38 * Pause for SIGUSR1 if option specified.
41 * Loop if the proper options are given.
43 * Check return code, if system call failed (return=-1)
44 * if errno set == expected errno
45 * Issue sys call fails with expected return value and errno.
47 * Issue sys call fails with unexpected errno.
49 * Issue sys call returns unexpected value.
52 * Print errno log and/or timing stats if options given
53 * Delete the temporary directory(s)/file(s) created.
55 * Usage: <for command-line>
56 * fchown04 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
57 * where, -c n : Run n copies concurrently.
58 * -e : Turn on errno logging.
59 * -i n : Execute test n times.
60 * -I x : Execute test for x seconds.
61 * -P x : Pause for x seconds between iterations.
62 * -t : Turn on syscall timing.
65 * 07/2001 Ported by Wayne Boyer
68 * This test should be executed by 'non-super-user' only.
80 #include <sys/types.h>
86 #define MODE_RWX S_IRWXU | S_IRWXG | S_IRWXO
87 #define FILE_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
88 #define TEST_FILE1 "tfile_1"
89 #define TEST_FILE2 "tfile_2"
92 int setup1(); /* setup function to test chmod for EPERM */
93 int setup2(); /* setup function to test chmod for EBADF */
95 int fd1
; /* File descriptor for testfile1 */
96 int fd2
; /* File descriptor for testfile2 */
98 struct test_case_t
{ /* test case struct. to hold ref. test cond's */
105 1, "Process is not owner/root", EPERM
, setup1
}, {
106 2, "File descriptor is not valid", EBADF
, setup2
}, {
107 0, NULL
, 0, no_setup
}
110 char test_home
[PATH_MAX
]; /* variable to hold TESTHOME env */
111 char *TCID
= "fchown04"; /* Test program identifier. */
112 int TST_TOTAL
= 2; /* Total number of test cases. */
113 extern int Tst_count
; /* Test Case counter for tst_* routines */
114 int exp_enos
[] = { EPERM
, EBADF
, 0 };
116 char bin_uid
[] = "bin";
117 struct passwd
*ltpuser
;
119 void setup(); /* Main setup function for the tests */
120 void cleanup(); /* cleanup function for the test */
122 int main(int ac
, char **av
)
124 int lc
; /* loop counter */
125 char *msg
; /* message returned from parse_opts */
126 char *test_desc
; /* test specific error message */
127 int fd
; /* test file descriptor */
128 int ind
; /* counter to test different test conditions */
129 uid_t User_id
; /* Effective user id of a test process */
130 gid_t Group_id
; /* Effective group id of a test process */
132 /* Parse standard options given to run the test. */
133 msg
= parse_opts(ac
, av
, (option_t
*) NULL
, NULL
);
134 if (msg
!= (char *)NULL
) {
135 tst_brkm(TBROK
, NULL
, "OPTION PARSING ERROR - %s", msg
);
140 * Invoke setup function to call individual test setup functions
141 * to simulate test conditions.
145 /* set the expected errnos... */
146 TEST_EXP_ENOS(exp_enos
);
148 /* Set uid/gid values to that of test process */
150 Group_id
= getegid();
152 /* Check looping state if -i option given */
153 for (lc
= 0; TEST_LOOPING(lc
); lc
++) {
154 /* Reset Tst_count in case we are looping. */
157 for (ind
= 0; Test_cases
[ind
].desc
!= NULL
; ind
++) {
158 fd
= Test_cases
[ind
].fd
;
159 test_desc
= Test_cases
[ind
].desc
;
168 * Call fchown(2) to test different test conditions.
169 * verify that it fails with -1 return value and
170 * sets appropriate errno.
172 TEST(fchown(fd
, User_id
, Group_id
));
174 /* Check return code from fchown(2) */
175 if (TEST_RETURN
== -1) {
176 TEST_ERROR_LOG(TEST_ERRNO
);
177 if (TEST_ERRNO
== Test_cases
[ind
].exp_errno
) {
179 "fchown() fails, %s, errno:%d",
180 test_desc
, TEST_ERRNO
);
182 tst_resm(TFAIL
, "fchown() fails, %s, "
183 "errno:%d, expected errno:%d",
184 test_desc
, TEST_ERRNO
,
185 Test_cases
[ind
].exp_errno
);
188 tst_resm(TFAIL
, "fchown() returned %d, expected"
189 " -1, errno:%d", TEST_RETURN
,
190 Test_cases
[ind
].exp_errno
);
192 } /* End of TEST CASE LOOPING. */
194 } /* End for TEST_LOOPING */
197 * Invoke cleanup() to delete the test directory/file(s) created
202 /*NOTREACHED*/ return (0);
206 * setup(void) - performs all ONE TIME setup for this test.
208 * Exit the test program on receipt of unexpected signals.
209 * Create a temporary directory and change directory to it.
210 * Invoke individual test setup functions according to the order
211 * set in struct. definition.
215 int ind
; /* counter for setup functions */
217 ltpuser
= getpwnam(bin_uid
);
219 /* Capture unexpected signals */
220 tst_sig(FORK
, DEF_HANDLER
, cleanup
);
222 /* Pause if that option was specified */
225 //changed by prashant yendigeri because the temp directory creating and deletinI// are with different uids, so this test case will fail in most of the scenario.
226 /* Make a temp dir and cd to it */
229 /* Get the current working directory of the process */
230 if (getcwd(test_home
, sizeof(test_home
)) == NULL
) {
231 tst_brkm(TBROK
, cleanup
,
232 "getcwd(3) fails to get working directory of process");
235 /* Switch to bin user for correct error code collection */
236 if (geteuid() != 0) {
237 tst_brkm(TBROK
, tst_exit
, "Test must be run as root");
240 /* to let chown(TESTDIR, -1, getgid()) in tst_tmpdir() run
241 * successfully even if getgid() is not in group_info of
242 * the current process's task_struct till now
245 initgroups("root", getgid());
247 if (setegid(ltpuser
->pw_uid
) == -1) {
248 tst_resm(TINFO
, "setegid failed to "
249 "to set the effective gid to %d", ltpuser
->pw_uid
);
252 if (seteuid(ltpuser
->pw_uid
) == -1) {
253 tst_resm(TINFO
, "seteuid failed to "
254 "to set the effective uid to %d", ltpuser
->pw_uid
);
257 //prashant yendigeri added the below line
258 /* Make a temp dir and cd to it */
261 /* call individual setup functions */
262 for (ind
= 0; Test_cases
[ind
].desc
!= NULL
; ind
++) {
263 Test_cases
[ind
].setupfunc();
268 * setup1() - setup function for a test condition for which fchown(2)
269 * returns -1 and sets errno to EPERM.
271 * Create a test file under temporary directory.
272 * Get the current working directory of the process and invoke setuid
273 * to root program to change the ownership of testfile to that of
278 int old_uid
, old_gid
;
279 struct passwd
* nobody
;
281 /* Create a testfile under temporary directory */
282 if ((fd1
= open(TEST_FILE1
, O_RDWR
| O_CREAT
, 0666)) == -1) {
283 tst_brkm(TBROK
, cleanup
,
284 "open(%s, O_RDWR|O_CREAT, 0666) failed, errno=%d : %s",
285 TEST_FILE1
, errno
, strerror(errno
));
292 if(!(nobody
=getpwnam("nobody")))
293 tst_brkm(TBROK
, cleanup
,
294 "Couldn't find user nobody: %s", strerror(errno
));
296 if(fchown(fd1
, nobody
->pw_uid
, nobody
->pw_gid
)<0)
297 tst_brkm(TBROK
, cleanup
,
298 "Fail to modify %s ownership(s)! %s", TEST_FILE1
, strerror(errno
));
307 * setup2() - setup function for a test condition for which fchown(2)
308 * returns -1 and sets errno to EBADF.
310 * Create a testfile under temporary directory and close it such that
311 * fchown(2) attempts to modify the file which is already closed.
315 /* Create a testfile under temporary directory */
316 if ((fd2
= open(TEST_FILE2
, O_RDWR
| O_CREAT
, 0666)) == -1) {
317 tst_brkm(TBROK
, cleanup
,
318 "open(%s, O_RDWR|O_CREAT, 0666) failed, errno=%d : %s",
319 TEST_FILE2
, errno
, strerror(errno
));
322 /* Close the testfile opened above */
323 if (close(fd2
) == -1) {
324 tst_brkm(TBROK
, cleanup
, "close(%s) Failed, errno=%d : %s",
325 TEST_FILE2
, errno
, strerror(errno
));
331 * no_setup() - Some test conditions for mknod(2) do not any setup.
332 * Hence, this function just returns 0.
340 * cleanup() - Performs all ONE TIME cleanup for this test at
341 * completion or premature exit.
343 * Print test timing stats and errno log if test executed with options.
344 * Close the testfile if still opened.
345 * Remove temporary directory and sub-directories/files under it
346 * created during setup().
347 * Exit the test program with normal exit code.
352 * print timing stats if that option was specified.
353 * print errno log if that option was specified.
357 if (close(fd1
) == -1) {
358 tst_brkm(TBROK
, NULL
, "close(%s) Failed, errno=%d : %s",
359 TEST_FILE1
, errno
, strerror(errno
));
362 /* Remove files and temporary directory created */
365 /* exit with return code appropriate for results */
367 } /* End cleanup() */