1 /* 2 * 3 * Copyright (c) International Business Machines Corp., 2001 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 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 /* 21 * Test Description: 22 * Verify that access() succeeds to check the existence or read/write/execute 23 * permissions on a file if the mode argument passed was F_OK/R_OK/W_OK/X_OK. 24 * 25 * Also verify that, access() succeeds to test the accessibility of the file 26 * referred to by symbolic link if the pathname points to a symbolic link. 27 * 28 * As well as verify that, these test files can be 29 * stat/read/written/executed indeed as root and nobody respectively. 30 * 31 * 07/2001 Ported by Wayne Boyera 32 * 06/2016 Modified by Guangwen Feng <fenggw-fnst (at) cn.fujitsu.com> 33 */ 34 35 #include <sys/types.h> 36 #include <unistd.h> 37 #include <errno.h> 38 #include <pwd.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <paths.h> 42 #include "tst_test.h" 43 44 #define FNAME_F "file_f" 45 #define FNAME_R "file_r" 46 #define FNAME_W "file_w" 47 #define FNAME_X "file_x" 48 #define SNAME_F "symlink_f" 49 #define SNAME_R "symlink_r" 50 #define SNAME_W "symlink_w" 51 #define SNAME_X "symlink_x" 52 53 static uid_t uid; 54 55 static struct tcase { 56 const char *pathname; 57 int mode; 58 char *name; 59 const char *targetname; 60 } tcases[] = { 61 {FNAME_F, F_OK, "F_OK", FNAME_F}, 62 {FNAME_R, R_OK, "R_OK", FNAME_R}, 63 {FNAME_W, W_OK, "W_OK", FNAME_W}, 64 {FNAME_X, X_OK, "X_OK", FNAME_X}, 65 {SNAME_F, F_OK, "F_OK", FNAME_F}, 66 {SNAME_R, R_OK, "R_OK", FNAME_R}, 67 {SNAME_W, W_OK, "W_OK", FNAME_W}, 68 {SNAME_X, X_OK, "X_OK", FNAME_X} 69 }; 70 71 static void access_test(struct tcase *tc, const char *user) 72 { 73 struct stat stat_buf; 74 char command[64]; 75 76 TEST(access(tc->pathname, tc->mode)); 77 78 if (TST_RET == -1) { 79 tst_res(TFAIL | TTERRNO, "access(%s, %s) as %s failed", 80 tc->pathname, tc->name, user); 81 return; 82 } 83 84 switch (tc->mode) { 85 case F_OK: 86 /* 87 * The specified file(or pointed to by symbolic link) 88 * exists, attempt to get its status, if successful, 89 * access() behaviour is correct. 90 */ 91 TEST(stat(tc->targetname, &stat_buf)); 92 93 if (TST_RET == -1) { 94 tst_res(TFAIL | TTERRNO, "stat(%s) as %s failed", 95 tc->targetname, user); 96 return; 97 } 98 99 break; 100 case R_OK: 101 /* 102 * The specified file(or pointed to by symbolic link) 103 * has read access, attempt to open the file with O_RDONLY, 104 * if we get a valid fd, access() behaviour is correct. 105 */ 106 TEST(open(tc->targetname, O_RDONLY)); 107 108 if (TST_RET == -1) { 109 tst_res(TFAIL | TTERRNO, 110 "open %s with O_RDONLY as %s failed", 111 tc->targetname, user); 112 return; 113 } 114 115 SAFE_CLOSE(TST_RET); 116 117 break; 118 case W_OK: 119 /* 120 * The specified file(or pointed to by symbolic link) 121 * has write access, attempt to open the file with O_WRONLY, 122 * if we get a valid fd, access() behaviour is correct. 123 */ 124 TEST(open(tc->targetname, O_WRONLY)); 125 126 if (TST_RET == -1) { 127 tst_res(TFAIL | TTERRNO, 128 "open %s with O_WRONLY as %s failed", 129 tc->targetname, user); 130 return; 131 } 132 133 SAFE_CLOSE(TST_RET); 134 135 break; 136 case X_OK: 137 /* 138 * The specified file(or pointed to by symbolic link) 139 * has execute access, attempt to execute the executable 140 * file, if successful, access() behaviour is correct. 141 */ 142 sprintf(command, "./%s", tc->targetname); 143 144 TEST(system(command)); 145 146 if (TST_RET != 0) { 147 tst_res(TFAIL | TTERRNO, "execute %s as %s failed", 148 tc->targetname, user); 149 return; 150 } 151 152 break; 153 default: 154 break; 155 } 156 157 tst_res(TPASS, "access(%s, %s) as %s behaviour is correct.", 158 tc->pathname, tc->name, user); 159 } 160 161 static void verify_access(unsigned int n) 162 { 163 struct tcase *tc = &tcases[n]; 164 pid_t pid; 165 166 /* test as root */ 167 access_test(tc, "root"); 168 169 /* test as nobody */ 170 pid = SAFE_FORK(); 171 if (pid) { 172 SAFE_WAITPID(pid, NULL, 0); 173 } else { 174 SAFE_SETUID(uid); 175 access_test(tc, "nobody"); 176 } 177 } 178 179 static void setup(void) 180 { 181 struct passwd *pw; 182 183 pw = SAFE_GETPWNAM("nobody"); 184 185 uid = pw->pw_uid; 186 187 SAFE_TOUCH(FNAME_F, 0000, NULL); 188 SAFE_TOUCH(FNAME_R, 0444, NULL); 189 SAFE_TOUCH(FNAME_W, 0222, NULL); 190 SAFE_TOUCH(FNAME_X, 0555, NULL); 191 SAFE_FILE_PRINTF(FNAME_X, "#!%s\n", _PATH_BSHELL); 192 193 SAFE_SYMLINK(FNAME_F, SNAME_F); 194 SAFE_SYMLINK(FNAME_R, SNAME_R); 195 SAFE_SYMLINK(FNAME_W, SNAME_W); 196 SAFE_SYMLINK(FNAME_X, SNAME_X); 197 } 198 199 static struct tst_test test = { 200 .tcnt = ARRAY_SIZE(tcases), 201 .needs_tmpdir = 1, 202 .needs_root = 1, 203 .forks_child = 1, 204 .setup = setup, 205 .test = verify_access, 206 }; 207