1 /* 2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. 3 * AUTHOR : William Roske 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 * 13 * Further, this software is distributed without any warranty that it is 14 * free of the rightful claim of any third person regarding infringement 15 * or the like. Any license provided herein, whether implied or 16 * otherwise, applies only to this software file. Patent licenses, if 17 * any, provided herein do not apply to combinations of this program with 18 * other software, or any other product whatsoever. 19 * 20 * You should have received a copy of the GNU General Public License along 21 * with this program; if not, write the Free Software Foundation, Inc., 22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 * 24 */ 25 /* 26 * Basic test for access(2) using F_OK, R_OK, W_OK and X_OK 27 */ 28 #include <errno.h> 29 #include <unistd.h> 30 #include <sys/types.h> 31 #include <pwd.h> 32 #include "tst_test.h" 33 34 #define FNAME_RWX "accessfile_rwx" 35 #define FNAME_R "accesfile_r" 36 #define FNAME_W "accesfile_w" 37 #define FNAME_X "accesfile_x" 38 39 static uid_t uid; 40 41 static struct tcase { 42 const char *fname; 43 int mode; 44 char *name; 45 int exp_errno; 46 /* 1: nobody expected 2: root expected 3: both */ 47 int exp_user; 48 } tcases[] = { 49 {FNAME_RWX, F_OK, "F_OK", 0, 3}, 50 {FNAME_RWX, X_OK, "X_OK", 0, 3}, 51 {FNAME_RWX, W_OK, "W_OK", 0, 3}, 52 {FNAME_RWX, R_OK, "R_OK", 0, 3}, 53 54 {FNAME_RWX, R_OK|W_OK, "R_OK|W_OK", 0, 3}, 55 {FNAME_RWX, R_OK|X_OK, "R_OK|X_OK", 0, 3}, 56 {FNAME_RWX, W_OK|X_OK, "W_OK|X_OK", 0, 3}, 57 {FNAME_RWX, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", 0, 3}, 58 59 {FNAME_X, X_OK, "X_OK", 0, 3}, 60 {FNAME_W, W_OK, "W_OK", 0, 3}, 61 {FNAME_R, R_OK, "R_OK", 0, 3}, 62 63 {FNAME_R, X_OK, "X_OK", EACCES, 3}, 64 {FNAME_R, W_OK, "W_OK", EACCES, 1}, 65 {FNAME_W, R_OK, "R_OK", EACCES, 1}, 66 {FNAME_W, X_OK, "X_OK", EACCES, 3}, 67 {FNAME_X, R_OK, "R_OK", EACCES, 1}, 68 {FNAME_X, W_OK, "W_OK", EACCES, 1}, 69 70 {FNAME_R, W_OK|X_OK, "W_OK|X_OK", EACCES, 3}, 71 {FNAME_R, R_OK|X_OK, "R_OK|X_OK", EACCES, 3}, 72 {FNAME_R, R_OK|W_OK, "R_OK|W_OK", EACCES, 1}, 73 {FNAME_R, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", EACCES, 3}, 74 75 {FNAME_W, W_OK|X_OK, "W_OK|X_OK", EACCES, 3}, 76 {FNAME_W, R_OK|X_OK, "R_OK|X_OK", EACCES, 3}, 77 {FNAME_W, R_OK|W_OK, "R_OK|W_OK", EACCES, 1}, 78 {FNAME_W, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", EACCES, 3}, 79 80 {FNAME_X, W_OK|X_OK, "W_OK|X_OK", EACCES, 1}, 81 {FNAME_X, R_OK|X_OK, "R_OK|X_OK", EACCES, 1}, 82 {FNAME_X, R_OK|W_OK, "R_OK|W_OK", EACCES, 1}, 83 {FNAME_X, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", EACCES, 1}, 84 85 {FNAME_R, W_OK, "W_OK", 0, 2}, 86 {FNAME_R, R_OK|W_OK, "R_OK|W_OK", 0, 2}, 87 88 {FNAME_W, R_OK, "R_OK", 0, 2}, 89 {FNAME_W, R_OK|W_OK, "R_OK|W_OK", 0, 2}, 90 91 {FNAME_X, R_OK, "R_OK", 0, 2}, 92 {FNAME_X, W_OK, "W_OK", 0, 2}, 93 {FNAME_X, R_OK|W_OK, "R_OK|W_OK", 0, 2} 94 }; 95 96 static void verify_success(struct tcase *tc, const char *user) 97 { 98 if (TEST_RETURN == -1) { 99 tst_res(TFAIL | TTERRNO, 100 "access(%s, %s) as %s failed unexpectedly", 101 tc->fname, tc->name, user); 102 return; 103 } 104 105 tst_res(TPASS, "access(%s, %s) as %s", tc->fname, tc->name, user); 106 } 107 108 static void verify_failure(struct tcase *tc, const char *user) 109 { 110 if (TEST_RETURN != -1) { 111 tst_res(TFAIL, "access(%s, %s) as %s succeded unexpectedly", 112 tc->fname, tc->name, user); 113 return; 114 } 115 116 if (TEST_ERRNO != tc->exp_errno) { 117 tst_res(TFAIL | TTERRNO, 118 "access(%s, %s) as %s should fail with %s", 119 tc->fname, tc->name, user, 120 tst_strerrno(tc->exp_errno)); 121 return; 122 } 123 124 tst_res(TPASS | TTERRNO, "access(%s, %s) as %s", 125 tc->fname, tc->name, user); 126 } 127 128 static void access_test(struct tcase *tc, const char *user) 129 { 130 TEST(access(tc->fname, tc->mode)); 131 132 if (tc->exp_errno) 133 verify_failure(tc, user); 134 else 135 verify_success(tc, user); 136 } 137 138 static void verify_access(unsigned int n) 139 { 140 struct tcase *tc = tcases + n; 141 pid_t pid; 142 143 if (tc->exp_user & 0x02) 144 access_test(tc, "root"); 145 146 if (tc->exp_user & 0x01) { 147 pid = SAFE_FORK(); 148 if (pid) { 149 SAFE_WAITPID(pid, NULL, 0); 150 } else { 151 SAFE_SETUID(uid); 152 access_test(tc, "nobody"); 153 } 154 } 155 } 156 157 static void setup(void) 158 { 159 struct passwd *pw; 160 161 pw = SAFE_GETPWNAM("nobody"); 162 163 uid = pw->pw_uid; 164 165 SAFE_TOUCH(FNAME_RWX, 0777, NULL); 166 SAFE_TOUCH(FNAME_R, 0444, NULL); 167 SAFE_TOUCH(FNAME_W, 0222, NULL); 168 SAFE_TOUCH(FNAME_X, 0111, NULL); 169 } 170 171 static struct tst_test test = { 172 .tid = "access01", 173 .needs_tmpdir = 1, 174 .needs_root = 1, 175 .forks_child = 1, 176 .setup = setup, 177 .test = verify_access, 178 .tcnt = ARRAY_SIZE(tcases), 179 }; 180