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 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 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 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 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