Delete the change_owner binary, as it is an insecure suid root binary; rewrite tests...
[ltp-debian.git] / testcases / kernel / syscalls / fchown / fchown04.c
blob789a1e65808946c12bc8975a881c6cdf7f447a27
1 /*
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
21 * Test Name: fchown04
23 * Test Description:
24 * Verify that,
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
27 * not super user.
28 * 2) fchown(2) returns -1 and sets errno to EBADF if the file descriptor
29 * of the specified file is not valid.
31 * Expected Result:
32 * fchown() should fail with return value -1 and set expected errno.
34 * Algorithm:
35 * Setup:
36 * Setup signal handling.
37 * Create temporary directory.
38 * Pause for SIGUSR1 if option specified.
40 * Test:
41 * Loop if the proper options are given.
42 * Execute system call
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.
46 * Otherwise,
47 * Issue sys call fails with unexpected errno.
48 * Otherwise,
49 * Issue sys call returns unexpected value.
51 * Cleanup:
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.
64 * HISTORY
65 * 07/2001 Ported by Wayne Boyer
67 * RESTRICTIONS:
68 * This test should be executed by 'non-super-user' only.
71 #include <stdio.h>
72 #include <stdlib.h>
73 #include <unistd.h>
74 #include <fcntl.h>
75 #include <errno.h>
76 #include <string.h>
77 #include <signal.h>
78 #include <grp.h>
79 #include <pwd.h>
80 #include <sys/types.h>
81 #include <sys/stat.h>
83 #include "test.h"
84 #include "usctest.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"
91 int no_setup();
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 */
99 int fd;
100 char *desc;
101 int exp_errno;
102 int (*setupfunc) ();
103 } Test_cases[] = {
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);
136 tst_exit();
140 * Invoke setup function to call individual test setup functions
141 * to simulate test conditions.
143 setup();
145 /* set the expected errnos... */
146 TEST_EXP_ENOS(exp_enos);
148 /* Set uid/gid values to that of test process */
149 User_id = geteuid();
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. */
155 Tst_count = 0;
157 for (ind = 0; Test_cases[ind].desc != NULL; ind++) {
158 fd = Test_cases[ind].fd;
159 test_desc = Test_cases[ind].desc;
161 if (fd == 1) {
162 fd = fd1;
163 } else {
164 fd = fd2;
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) {
178 tst_resm(TPASS,
179 "fchown() fails, %s, errno:%d",
180 test_desc, TEST_ERRNO);
181 } else {
182 tst_resm(TFAIL, "fchown() fails, %s, "
183 "errno:%d, expected errno:%d",
184 test_desc, TEST_ERRNO,
185 Test_cases[ind].exp_errno);
187 } else {
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
198 * in the setup().
200 cleanup();
202 /*NOTREACHED*/ return (0);
203 } /* End main */
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.
213 void setup()
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 */
223 TEST_PAUSE;
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 */
227 // tst_tmpdir();
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);
250 perror("setegid");
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);
255 perror("seteuid");
257 //prashant yendigeri added the below line
258 /* Make a temp dir and cd to it */
259 tst_tmpdir();
261 /* call individual setup functions */
262 for (ind = 0; Test_cases[ind].desc != NULL; ind++) {
263 Test_cases[ind].setupfunc();
265 } /* End setup() */
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
274 * "ltpuser2" user.
276 int setup1()
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));
288 old_uid=geteuid();
289 old_gid=getegid();
290 seteuid(0);
291 setegid(0);
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));
300 seteuid(old_uid);
301 setegid(old_gid);
303 return 0;
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.
313 int setup2()
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));
327 return 0;
331 * no_setup() - Some test conditions for mknod(2) do not any setup.
332 * Hence, this function just returns 0.
334 int no_setup()
336 return 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.
349 void cleanup()
352 * print timing stats if that option was specified.
353 * print errno log if that option was specified.
355 TEST_CLEANUP;
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 */
363 tst_rmdir();
365 /* exit with return code appropriate for results */
366 tst_exit();
367 } /* End cleanup() */