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