1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) 2023 FUJITSU LIMITED. All rights reserved. 4 * Copyright (c) Linux Test Project, 2003-2023 5 * Author: Yang Xu <xuyang2018.jy@fujitsu.com> 6 */ 7 8/*\ 9 * [Description] 10 * 11 * Test basic error handling of faccessat2 syscall: 12 * 13 * - faccessat2() fails with EFAULT if pathname is a bad pathname point. 14 * - faccessat2() fails with EINVAL if flags is -1. 15 * - faccessat2() fails with EINVAL if mode is -1. 16 * - faccessat2() fails with EBADF if dirfd is -1. 17 * - faccessat2() fails with ENOTDIR if pathname is relative path to a 18 * file and dir_fd is file descriptor for this file. 19 * - faccessat2() fails with EACCES if flags is AT_EACCESS and not using 20 * the effective user and group IDs. 21 * 22 * Minimum Linux version required is v5.8. 23 */ 24 25#include <pwd.h> 26 27#include "tst_test.h" 28#include "lapi/syscalls.h" 29#include "lapi/faccessat.h" 30 31#define TESTUSER "nobody" 32#define TESTDIR "faccessat2dir" 33#define RELPATH "faccessat2dir/faccessat2file" 34 35static int fd; 36static int bad_fd = -1; 37static int atcwd_fd = AT_FDCWD; 38static char *bad_path; 39static char *rel_path; 40 41static struct passwd *ltpuser; 42 43static struct tcase { 44 int *fd; 45 char **filename; 46 int mode; 47 int flags; 48 int exp_errno; 49 const char *desc; 50} tcases[] = { 51 {&atcwd_fd, &bad_path, R_OK, 0, EFAULT, "invalid address"}, 52 {&atcwd_fd, &rel_path, R_OK, -1, EINVAL, "invalid flags"}, 53 {&atcwd_fd, &rel_path, -1, 0, EINVAL, "invalid mode"}, 54 {&bad_fd, &rel_path, R_OK, 0, EBADF, "invalid fd"}, 55 {&fd, &rel_path, R_OK, 0, ENOTDIR, "fd pointing to file"}, 56 {&atcwd_fd, &rel_path, R_OK, AT_EACCESS, EACCES, 57 "AT_EACCESS and unprivileged EUID"}, 58}; 59 60static void verify_faccessat2(unsigned int i) 61{ 62 struct tcase *tc = &tcases[i]; 63 64 if (tc->exp_errno == EACCES) 65 SAFE_SETEUID(ltpuser->pw_uid); 66 67 TST_EXP_FAIL(faccessat2(*tc->fd, *tc->filename, tc->mode, tc->flags), 68 tc->exp_errno, "faccessat2() with %s", tc->desc); 69 70 if (tc->exp_errno == EACCES) 71 SAFE_SETEUID(0); 72} 73 74static void setup(void) 75{ 76 SAFE_MKDIR(TESTDIR, 0666); 77 SAFE_TOUCH(RELPATH, 0444, NULL); 78 79 fd = SAFE_OPEN(RELPATH, O_RDONLY); 80 bad_path = tst_get_bad_addr(NULL); 81 82 ltpuser = SAFE_GETPWNAM(TESTUSER); 83} 84 85static void cleanup(void) 86{ 87 if (fd > -1) 88 SAFE_CLOSE(fd); 89} 90 91static struct tst_test test = { 92 .test = verify_faccessat2, 93 .tcnt = ARRAY_SIZE(tcases), 94 .setup = setup, 95 .cleanup = cleanup, 96 .bufs = (struct tst_buffers []) { 97 {&rel_path, .str = RELPATH}, 98 {}, 99 }, 100 .needs_tmpdir = 1, 101 .needs_root = 1, 102}; 103