1 /*
2 * Copyright (c) International Business Machines Corp., 2001
3 * 07/2001 Ported by Wayne Boyer
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 Foundation,
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 /*
21 * Test Description:
22 * Verify that,
23 * 1) fchown(2) returns -1 and sets errno to EPERM if the effective user id
24 * of process does not match the owner of the file and the process is
25 * not super user.
26 * 2) fchown(2) returns -1 and sets errno to EBADF if the file descriptor
27 * of the specified file is not valid.
28 * 3) fchown(2) returns -1 and sets errno to EROFS if the named file resides
29 * on a read-only file system.
30 */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <fcntl.h>
36 #include <errno.h>
37 #include <string.h>
38 #include <signal.h>
39 #include <grp.h>
40 #include <pwd.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <sys/mount.h>
44
45 #include "test.h"
46 #include "safe_macros.h"
47 #include "compat_16.h"
48
49 #define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \
50 S_IXGRP|S_IROTH|S_IXOTH)
51
52 static int fd1;
53 static int fd2 = -1;
54 static int fd3;
55 static const char *device;
56 static int mount_flag;
57
58 static struct test_case_t {
59 int *fd;
60 int exp_errno;
61 } test_cases[] = {
62 {&fd1, EPERM},
63 {&fd2, EBADF},
64 {&fd3, EROFS},
65 };
66
67 TCID_DEFINE(fchown04);
68 int TST_TOTAL = ARRAY_SIZE(test_cases);
69
70 static void setup(void);
71 static void fchown_verify(int);
72 static void cleanup(void);
73
main(int ac,char ** av)74 int main(int ac, char **av)
75 {
76 int lc;
77 int i;
78
79 tst_parse_opts(ac, av, NULL, NULL);
80
81 setup();
82
83 for (lc = 0; TEST_LOOPING(lc); lc++) {
84
85 tst_count = 0;
86
87 for (i = 0; i < TST_TOTAL; i++)
88 fchown_verify(i);
89 }
90
91 cleanup();
92 tst_exit();
93 }
94
setup(void)95 static void setup(void)
96 {
97 struct passwd *ltpuser;
98 const char *fs_type;
99
100 TEST_PAUSE;
101
102 tst_require_root();
103
104 tst_tmpdir();
105
106 fs_type = tst_dev_fs_type();
107 device = tst_acquire_device(cleanup);
108
109 if (!device)
110 tst_brkm(TCONF, cleanup, "Failed to acquire device");
111
112 tst_sig(NOFORK, DEF_HANDLER, cleanup);
113
114 fd1 = SAFE_OPEN(cleanup, "tfile_1", O_RDWR | O_CREAT, 0666);
115
116 tst_mkfs(cleanup, device, fs_type, NULL, NULL);
117 SAFE_MKDIR(cleanup, "mntpoint", DIR_MODE);
118 SAFE_MOUNT(cleanup, device, "mntpoint", fs_type, 0, NULL);
119 mount_flag = 1;
120 SAFE_TOUCH(cleanup, "mntpoint/tfile_3", 0644, NULL);
121 SAFE_MOUNT(cleanup, device, "mntpoint", fs_type,
122 MS_REMOUNT | MS_RDONLY, NULL);
123 fd3 = SAFE_OPEN(cleanup, "mntpoint/tfile_3", O_RDONLY);
124
125 ltpuser = SAFE_GETPWNAM(cleanup, "nobody");
126 SAFE_SETEUID(cleanup, ltpuser->pw_uid);
127 }
128
fchown_verify(int i)129 static void fchown_verify(int i)
130 {
131 UID16_CHECK(geteuid(), "fchown", cleanup)
132 GID16_CHECK(getegid(), "fchown", cleanup)
133
134 TEST(FCHOWN(cleanup, *test_cases[i].fd, geteuid(), getegid()));
135
136 if (TEST_RETURN == -1) {
137 if (TEST_ERRNO == test_cases[i].exp_errno) {
138 tst_resm(TPASS | TTERRNO, "fchown failed as expected");
139 } else {
140 tst_resm(TFAIL | TTERRNO,
141 "fchown failed unexpectedly; expected %d - %s",
142 test_cases[i].exp_errno,
143 strerror(test_cases[i].exp_errno));
144 }
145 } else {
146 tst_resm(TFAIL, "fchown passed unexpectedly");
147 }
148 }
149
cleanup(void)150 static void cleanup(void)
151 {
152 if (seteuid(0))
153 tst_resm(TWARN | TERRNO, "Failet to seteuid(0) before cleanup");
154
155 if (fd1 > 0 && close(fd1))
156 tst_resm(TWARN | TERRNO, "Failed to close fd1");
157
158 if (fd3 > 0 && close(fd3))
159 tst_resm(TWARN | TERRNO, "Failed to close fd3");
160
161 if (mount_flag && tst_umount("mntpoint") < 0)
162 tst_resm(TWARN | TERRNO, "umount device:%s failed", device);
163
164 if (device)
165 tst_release_device(device);
166
167 tst_rmdir();
168 }
169