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 if (mount(device, "mntpoint", fs_type, 0, NULL) < 0) {
119 tst_brkm(TBROK | TERRNO, cleanup,
120 "mount device:%s failed", device);
121 }
122 mount_flag = 1;
123 SAFE_TOUCH(cleanup, "mntpoint/tfile_3", 0644, NULL);
124 if (mount(device, "mntpoint", fs_type,
125 MS_REMOUNT | MS_RDONLY, NULL) < 0) {
126 tst_brkm(TBROK | TERRNO, cleanup,
127 "mount device:%s failed", device);
128 }
129 fd3 = SAFE_OPEN(cleanup, "mntpoint/tfile_3", O_RDONLY);
130
131 ltpuser = SAFE_GETPWNAM(cleanup, "nobody");
132 SAFE_SETEUID(cleanup, ltpuser->pw_uid);
133 }
134
fchown_verify(int i)135 static void fchown_verify(int i)
136 {
137 UID16_CHECK(geteuid(), "fchown", cleanup)
138 GID16_CHECK(getegid(), "fchown", cleanup)
139
140 TEST(FCHOWN(cleanup, *test_cases[i].fd, geteuid(), getegid()));
141
142 if (TEST_RETURN == -1) {
143 if (TEST_ERRNO == test_cases[i].exp_errno) {
144 tst_resm(TPASS | TTERRNO, "fchown failed as expected");
145 } else {
146 tst_resm(TFAIL | TTERRNO,
147 "fchown failed unexpectedly; expected %d - %s",
148 test_cases[i].exp_errno,
149 strerror(test_cases[i].exp_errno));
150 }
151 } else {
152 tst_resm(TFAIL, "fchown passed unexpectedly");
153 }
154 }
155
cleanup(void)156 static void cleanup(void)
157 {
158 if (seteuid(0))
159 tst_resm(TWARN | TERRNO, "Failet to seteuid(0) before cleanup");
160
161 if (fd1 > 0 && close(fd1))
162 tst_resm(TWARN | TERRNO, "Failed to close fd1");
163
164 if (fd3 > 0 && close(fd3))
165 tst_resm(TWARN | TERRNO, "Failed to close fd3");
166
167 if (mount_flag && tst_umount("mntpoint") < 0)
168 tst_resm(TWARN | TERRNO, "umount device:%s failed", device);
169
170 if (device)
171 tst_release_device(device);
172
173 tst_rmdir();
174 }
175