// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. * AUTHOR : William Roske */ /* * Basic test for access(2) using F_OK, R_OK, W_OK and X_OK */ #include #include #include #include #include "tst_test.h" #define FNAME_RWX "accessfile_rwx" #define FNAME_R "accessfile_r" #define FNAME_W "accessfile_w" #define FNAME_X "accessfile_x" #define DNAME_R "accessdir_r" #define DNAME_W "accessdir_w" #define DNAME_X "accessdir_x" #define DNAME_RW "accessdir_rw" #define DNAME_RX "accessdir_rx" #define DNAME_WX "accessdir_wx" static uid_t uid; static struct tcase { const char *fname; int mode; char *name; int exp_errno; /* 1: nobody expected 2: root expected 3: both */ int exp_user; } tcases[] = { {FNAME_RWX, F_OK, "F_OK", 0, 3}, {FNAME_RWX, X_OK, "X_OK", 0, 3}, {FNAME_RWX, W_OK, "W_OK", 0, 3}, {FNAME_RWX, R_OK, "R_OK", 0, 3}, {FNAME_RWX, R_OK|W_OK, "R_OK|W_OK", 0, 3}, {FNAME_RWX, R_OK|X_OK, "R_OK|X_OK", 0, 3}, {FNAME_RWX, W_OK|X_OK, "W_OK|X_OK", 0, 3}, {FNAME_RWX, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", 0, 3}, {FNAME_X, X_OK, "X_OK", 0, 3}, {FNAME_W, W_OK, "W_OK", 0, 3}, {FNAME_R, R_OK, "R_OK", 0, 3}, {FNAME_R, X_OK, "X_OK", EACCES, 3}, {FNAME_R, W_OK, "W_OK", EACCES, 1}, {FNAME_W, R_OK, "R_OK", EACCES, 1}, {FNAME_W, X_OK, "X_OK", EACCES, 3}, {FNAME_X, R_OK, "R_OK", EACCES, 1}, {FNAME_X, W_OK, "W_OK", EACCES, 1}, {FNAME_R, W_OK|X_OK, "W_OK|X_OK", EACCES, 3}, {FNAME_R, R_OK|X_OK, "R_OK|X_OK", EACCES, 3}, {FNAME_R, R_OK|W_OK, "R_OK|W_OK", EACCES, 1}, {FNAME_R, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", EACCES, 3}, {FNAME_W, W_OK|X_OK, "W_OK|X_OK", EACCES, 3}, {FNAME_W, R_OK|X_OK, "R_OK|X_OK", EACCES, 3}, {FNAME_W, R_OK|W_OK, "R_OK|W_OK", EACCES, 1}, {FNAME_W, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", EACCES, 3}, {FNAME_X, W_OK|X_OK, "W_OK|X_OK", EACCES, 1}, {FNAME_X, R_OK|X_OK, "R_OK|X_OK", EACCES, 1}, {FNAME_X, R_OK|W_OK, "R_OK|W_OK", EACCES, 1}, {FNAME_X, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", EACCES, 1}, {FNAME_R, W_OK, "W_OK", 0, 2}, {FNAME_R, R_OK|W_OK, "R_OK|W_OK", 0, 2}, {FNAME_W, R_OK, "R_OK", 0, 2}, {FNAME_W, R_OK|W_OK, "R_OK|W_OK", 0, 2}, {FNAME_X, R_OK, "R_OK", 0, 2}, {FNAME_X, W_OK, "W_OK", 0, 2}, {FNAME_X, R_OK|W_OK, "R_OK|W_OK", 0, 2}, {DNAME_R"/"FNAME_R, F_OK, "F_OK", 0, 2}, {DNAME_R"/"FNAME_R, R_OK, "R_OK", 0, 2}, {DNAME_R"/"FNAME_R, W_OK, "W_OK", 0, 2}, {DNAME_R"/"FNAME_W, F_OK, "F_OK", 0, 2}, {DNAME_R"/"FNAME_W, R_OK, "R_OK", 0, 2}, {DNAME_R"/"FNAME_W, W_OK, "W_OK", 0, 2}, {DNAME_R"/"FNAME_X, F_OK, "F_OK", 0, 2}, {DNAME_R"/"FNAME_X, R_OK, "R_OK", 0, 2}, {DNAME_R"/"FNAME_X, W_OK, "W_OK", 0, 2}, {DNAME_R"/"FNAME_X, X_OK, "X_OK", 0, 2}, {DNAME_W"/"FNAME_R, F_OK, "F_OK", 0, 2}, {DNAME_W"/"FNAME_R, R_OK, "R_OK", 0, 2}, {DNAME_W"/"FNAME_R, W_OK, "W_OK", 0, 2}, {DNAME_W"/"FNAME_W, F_OK, "F_OK", 0, 2}, {DNAME_W"/"FNAME_W, R_OK, "R_OK", 0, 2}, {DNAME_W"/"FNAME_W, W_OK, "W_OK", 0, 2}, {DNAME_W"/"FNAME_X, F_OK, "F_OK", 0, 2}, {DNAME_W"/"FNAME_X, R_OK, "R_OK", 0, 2}, {DNAME_W"/"FNAME_X, W_OK, "W_OK", 0, 2}, {DNAME_W"/"FNAME_X, X_OK, "X_OK", 0, 2}, {DNAME_X"/"FNAME_R, F_OK, "F_OK", 0, 3}, {DNAME_X"/"FNAME_R, R_OK, "R_OK", 0, 3}, {DNAME_X"/"FNAME_R, W_OK, "W_OK", 0, 2}, {DNAME_X"/"FNAME_W, F_OK, "F_OK", 0, 3}, {DNAME_X"/"FNAME_W, R_OK, "R_OK", 0, 2}, {DNAME_X"/"FNAME_W, W_OK, "W_OK", 0, 3}, {DNAME_X"/"FNAME_X, F_OK, "F_OK", 0, 3}, {DNAME_X"/"FNAME_X, R_OK, "R_OK", 0, 2}, {DNAME_X"/"FNAME_X, W_OK, "W_OK", 0, 2}, {DNAME_X"/"FNAME_X, X_OK, "X_OK", 0, 3}, {DNAME_RW"/"FNAME_R, F_OK, "F_OK", 0, 2}, {DNAME_RW"/"FNAME_R, R_OK, "R_OK", 0, 2}, {DNAME_RW"/"FNAME_R, W_OK, "W_OK", 0, 2}, {DNAME_RW"/"FNAME_W, F_OK, "F_OK", 0, 2}, {DNAME_RW"/"FNAME_W, R_OK, "R_OK", 0, 2}, {DNAME_RW"/"FNAME_W, W_OK, "W_OK", 0, 2}, {DNAME_RW"/"FNAME_X, F_OK, "F_OK", 0, 2}, {DNAME_RW"/"FNAME_X, R_OK, "R_OK", 0, 2}, {DNAME_RW"/"FNAME_X, W_OK, "W_OK", 0, 2}, {DNAME_RW"/"FNAME_X, X_OK, "X_OK", 0, 2}, {DNAME_RX"/"FNAME_R, F_OK, "F_OK", 0, 3}, {DNAME_RX"/"FNAME_R, R_OK, "R_OK", 0, 3}, {DNAME_RX"/"FNAME_R, W_OK, "W_OK", 0, 2}, {DNAME_RX"/"FNAME_W, F_OK, "F_OK", 0, 3}, {DNAME_RX"/"FNAME_W, R_OK, "R_OK", 0, 2}, {DNAME_RX"/"FNAME_W, W_OK, "W_OK", 0, 3}, {DNAME_RX"/"FNAME_X, F_OK, "F_OK", 0, 3}, {DNAME_RX"/"FNAME_X, R_OK, "R_OK", 0, 2}, {DNAME_RX"/"FNAME_X, W_OK, "W_OK", 0, 2}, {DNAME_RX"/"FNAME_X, X_OK, "X_OK", 0, 3}, {DNAME_WX"/"FNAME_R, F_OK, "F_OK", 0, 3}, {DNAME_WX"/"FNAME_R, R_OK, "R_OK", 0, 3}, {DNAME_WX"/"FNAME_R, W_OK, "W_OK", 0, 2}, {DNAME_WX"/"FNAME_W, F_OK, "F_OK", 0, 3}, {DNAME_WX"/"FNAME_W, R_OK, "R_OK", 0, 2}, {DNAME_WX"/"FNAME_W, W_OK, "W_OK", 0, 3}, {DNAME_WX"/"FNAME_X, F_OK, "F_OK", 0, 3}, {DNAME_WX"/"FNAME_X, R_OK, "R_OK", 0, 2}, {DNAME_WX"/"FNAME_X, W_OK, "W_OK", 0, 2}, {DNAME_WX"/"FNAME_X, X_OK, "X_OK", 0, 3}, {DNAME_R"/"FNAME_R, F_OK, "F_OK", EACCES, 1}, {DNAME_R"/"FNAME_R, R_OK, "R_OK", EACCES, 1}, {DNAME_R"/"FNAME_R, W_OK, "W_OK", EACCES, 1}, {DNAME_R"/"FNAME_R, X_OK, "X_OK", EACCES, 3}, {DNAME_R"/"FNAME_W, F_OK, "F_OK", EACCES, 1}, {DNAME_R"/"FNAME_W, R_OK, "R_OK", EACCES, 1}, {DNAME_R"/"FNAME_W, W_OK, "W_OK", EACCES, 1}, {DNAME_R"/"FNAME_W, X_OK, "X_OK", EACCES, 3}, {DNAME_R"/"FNAME_X, F_OK, "F_OK", EACCES, 1}, {DNAME_R"/"FNAME_X, R_OK, "R_OK", EACCES, 1}, {DNAME_R"/"FNAME_X, W_OK, "W_OK", EACCES, 1}, {DNAME_R"/"FNAME_X, X_OK, "X_OK", EACCES, 1}, {DNAME_W"/"FNAME_R, F_OK, "F_OK", EACCES, 1}, {DNAME_W"/"FNAME_R, R_OK, "R_OK", EACCES, 1}, {DNAME_W"/"FNAME_R, W_OK, "W_OK", EACCES, 1}, {DNAME_W"/"FNAME_R, X_OK, "X_OK", EACCES, 3}, {DNAME_W"/"FNAME_W, F_OK, "F_OK", EACCES, 1}, {DNAME_W"/"FNAME_W, R_OK, "R_OK", EACCES, 1}, {DNAME_W"/"FNAME_W, W_OK, "W_OK", EACCES, 1}, {DNAME_W"/"FNAME_W, X_OK, "X_OK", EACCES, 3}, {DNAME_W"/"FNAME_X, F_OK, "F_OK", EACCES, 1}, {DNAME_W"/"FNAME_X, R_OK, "R_OK", EACCES, 1}, {DNAME_W"/"FNAME_X, W_OK, "W_OK", EACCES, 1}, {DNAME_W"/"FNAME_X, X_OK, "X_OK", EACCES, 1}, {DNAME_X"/"FNAME_R, W_OK, "W_OK", EACCES, 1}, {DNAME_X"/"FNAME_R, X_OK, "X_OK", EACCES, 3}, {DNAME_X"/"FNAME_W, R_OK, "R_OK", EACCES, 1}, {DNAME_X"/"FNAME_W, X_OK, "X_OK", EACCES, 3}, {DNAME_X"/"FNAME_X, R_OK, "R_OK", EACCES, 1}, {DNAME_X"/"FNAME_X, W_OK, "W_OK", EACCES, 1}, {DNAME_RW"/"FNAME_R, F_OK, "F_OK", EACCES, 1}, {DNAME_RW"/"FNAME_R, R_OK, "R_OK", EACCES, 1}, {DNAME_RW"/"FNAME_R, W_OK, "W_OK", EACCES, 1}, {DNAME_RW"/"FNAME_R, X_OK, "X_OK", EACCES, 3}, {DNAME_RW"/"FNAME_W, F_OK, "F_OK", EACCES, 1}, {DNAME_RW"/"FNAME_W, R_OK, "R_OK", EACCES, 1}, {DNAME_RW"/"FNAME_W, W_OK, "W_OK", EACCES, 1}, {DNAME_RW"/"FNAME_W, X_OK, "X_OK", EACCES, 3}, {DNAME_RW"/"FNAME_X, F_OK, "F_OK", EACCES, 1}, {DNAME_RW"/"FNAME_X, R_OK, "R_OK", EACCES, 1}, {DNAME_RW"/"FNAME_X, W_OK, "W_OK", EACCES, 1}, {DNAME_RW"/"FNAME_X, X_OK, "X_OK", EACCES, 1}, {DNAME_RX"/"FNAME_R, W_OK, "W_OK", EACCES, 1}, {DNAME_RX"/"FNAME_R, X_OK, "X_OK", EACCES, 3}, {DNAME_RX"/"FNAME_W, R_OK, "R_OK", EACCES, 1}, {DNAME_RX"/"FNAME_W, X_OK, "X_OK", EACCES, 3}, {DNAME_RX"/"FNAME_X, R_OK, "R_OK", EACCES, 1}, {DNAME_RX"/"FNAME_X, W_OK, "W_OK", EACCES, 1}, {DNAME_WX"/"FNAME_R, W_OK, "W_OK", EACCES, 1}, {DNAME_WX"/"FNAME_R, X_OK, "X_OK", EACCES, 3}, {DNAME_WX"/"FNAME_W, R_OK, "R_OK", EACCES, 1}, {DNAME_WX"/"FNAME_W, X_OK, "X_OK", EACCES, 3}, {DNAME_WX"/"FNAME_X, R_OK, "R_OK", EACCES, 1}, {DNAME_WX"/"FNAME_X, W_OK, "W_OK", EACCES, 1} }; static void access_test(struct tcase *tc, const char *user) { if (tc->exp_errno) { TST_EXP_FAIL(access(tc->fname, tc->mode), tc->exp_errno, "access(%s, %s) as %s", tc->fname, tc->name, user); } else { TST_EXP_PASS(access(tc->fname, tc->mode), "access(%s, %s) as %s", tc->fname, tc->name, user); } } static void verify_access(unsigned int n) { struct tcase *tc = tcases + n; pid_t pid; if (tc->exp_user & 0x02) access_test(tc, "root"); if (tc->exp_user & 0x01) { pid = SAFE_FORK(); if (pid) { SAFE_WAITPID(pid, NULL, 0); } else { SAFE_SETUID(uid); access_test(tc, "nobody"); } } } static void setup(void) { struct passwd *pw; umask(0022); pw = SAFE_GETPWNAM("nobody"); uid = pw->pw_uid; SAFE_TOUCH(FNAME_RWX, 0777, NULL); SAFE_TOUCH(FNAME_R, 0444, NULL); SAFE_TOUCH(FNAME_W, 0222, NULL); SAFE_TOUCH(FNAME_X, 0111, NULL); SAFE_MKDIR(DNAME_R, 0444); SAFE_MKDIR(DNAME_W, 0222); SAFE_MKDIR(DNAME_X, 0111); SAFE_MKDIR(DNAME_RW, 0666); SAFE_MKDIR(DNAME_RX, 0555); SAFE_MKDIR(DNAME_WX, 0333); SAFE_TOUCH(DNAME_R"/"FNAME_R, 0444, NULL); SAFE_TOUCH(DNAME_R"/"FNAME_W, 0222, NULL); SAFE_TOUCH(DNAME_R"/"FNAME_X, 0111, NULL); SAFE_TOUCH(DNAME_W"/"FNAME_R, 0444, NULL); SAFE_TOUCH(DNAME_W"/"FNAME_W, 0222, NULL); SAFE_TOUCH(DNAME_W"/"FNAME_X, 0111, NULL); SAFE_TOUCH(DNAME_X"/"FNAME_R, 0444, NULL); SAFE_TOUCH(DNAME_X"/"FNAME_W, 0222, NULL); SAFE_TOUCH(DNAME_X"/"FNAME_X, 0111, NULL); SAFE_TOUCH(DNAME_RW"/"FNAME_R, 0444, NULL); SAFE_TOUCH(DNAME_RW"/"FNAME_W, 0222, NULL); SAFE_TOUCH(DNAME_RW"/"FNAME_X, 0111, NULL); SAFE_TOUCH(DNAME_RX"/"FNAME_R, 0444, NULL); SAFE_TOUCH(DNAME_RX"/"FNAME_W, 0222, NULL); SAFE_TOUCH(DNAME_RX"/"FNAME_X, 0111, NULL); SAFE_TOUCH(DNAME_WX"/"FNAME_R, 0444, NULL); SAFE_TOUCH(DNAME_WX"/"FNAME_W, 0222, NULL); SAFE_TOUCH(DNAME_WX"/"FNAME_X, 0111, NULL); } static struct tst_test test = { .needs_tmpdir = 1, .needs_root = 1, .forks_child = 1, .setup = setup, .test = verify_access, .tcnt = ARRAY_SIZE(tcases), };