1 /* 2 * Copyright (c) International Business Machines Corp., 2001 3 * Copyright (c) 2013 Fujitsu Ltd. 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 the 13 * 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, see <http://www.gnu.org/licenses/>. 17 */ 18 19 /* 20 * Verify that, 21 * 1) access() fails with -1 return value and sets errno to EINVAL 22 * if the specified access mode argument is invalid. 23 * 2) access() fails with -1 return value and sets errno to ENOENT 24 * if the specified file doesn't exist (or pathname is NULL). 25 * 3) access() fails with -1 return value and sets errno to ENAMETOOLONG 26 * if the pathname size is > PATH_MAX characters. 27 * 4) access() fails with -1 return value and sets errno to ENOTDIR 28 * if a component used as a directory in pathname is not a directory. 29 * 5) access() fails with -1 return value and sets errno to ELOOP 30 * if too many symbolic links were encountered in resolving pathname. 31 * 6) access() fails with -1 return value and sets errno to EROFS 32 * if write permission was requested for files on a read-only file system. 33 * 34 * 07/2001 Ported by Wayne Boyer 35 * 11/2013 Ported by Xiaoguang Wang <wangxg.fnst (at) cn.fujitsu.com> 36 * 11/2016 Modified by Guangwen Feng <fenggw-fnst (at) cn.fujitsu.com> 37 */ 38 39 #include <errno.h> 40 #include <pwd.h> 41 #include <string.h> 42 #include <sys/mount.h> 43 #include <sys/types.h> 44 #include <unistd.h> 45 46 #include "tst_test.h" 47 48 #define FNAME1 "accessfile1" 49 #define FNAME2 "accessfile2/accessfile2" 50 #define DNAME "accessfile2" 51 #define SNAME1 "symlink1" 52 #define SNAME2 "symlink2" 53 #define MNT_POINT "mntpoint" 54 55 static uid_t uid; 56 static char longpathname[PATH_MAX + 2]; 57 58 static struct tcase { 59 const char *pathname; 60 int mode; 61 int exp_errno; 62 } tcases[] = { 63 {FNAME1, -1, EINVAL}, 64 {"", W_OK, ENOENT}, 65 {longpathname, R_OK, ENAMETOOLONG}, 66 {FNAME2, R_OK, ENOTDIR}, 67 {SNAME1, R_OK, ELOOP}, 68 {MNT_POINT, W_OK, EROFS} 69 }; 70 71 static void access_test(struct tcase *tc, const char *user) 72 { 73 TEST(access(tc->pathname, tc->mode)); 74 75 if (TEST_RETURN != -1) { 76 tst_res(TFAIL, "access as %s succeeded unexpectedly", user); 77 return; 78 } 79 80 if (tc->exp_errno != TEST_ERRNO) { 81 tst_res(TFAIL | TTERRNO, 82 "access as %s should fail with %s", 83 user, tst_strerrno(tc->exp_errno)); 84 return; 85 } 86 87 tst_res(TPASS | TTERRNO, "access as %s failed expectedly", user); 88 } 89 90 static void verify_access(unsigned int n) 91 { 92 struct tcase *tc = tcases + n; 93 pid_t pid; 94 95 access_test(tc, "root"); 96 97 pid = SAFE_FORK(); 98 if (pid) { 99 SAFE_WAITPID(pid, NULL, 0); 100 } else { 101 SAFE_SETUID(uid); 102 access_test(tc, "nobody"); 103 } 104 } 105 106 static void setup(void) 107 { 108 struct passwd *pw; 109 110 pw = SAFE_GETPWNAM("nobody"); 111 112 uid = pw->pw_uid; 113 114 memset(longpathname, 'a', sizeof(longpathname) - 1); 115 116 SAFE_TOUCH(FNAME1, 0333, NULL); 117 SAFE_TOUCH(DNAME, 0644, NULL); 118 119 SAFE_SYMLINK(SNAME1, SNAME2); 120 SAFE_SYMLINK(SNAME2, SNAME1); 121 } 122 123 static struct tst_test test = { 124 .tcnt = ARRAY_SIZE(tcases), 125 .needs_tmpdir = 1, 126 .needs_root = 1, 127 .forks_child = 1, 128 .needs_rofs = 1, 129 .mntpoint = MNT_POINT, 130 .setup = setup, 131 .test = verify_access, 132 }; 133