diff options
Diffstat (limited to 'testcases/kernel/syscalls/faccessat2')
-rw-r--r-- | testcases/kernel/syscalls/faccessat2/.gitignore | 2 | ||||
-rw-r--r-- | testcases/kernel/syscalls/faccessat2/Makefile | 9 | ||||
-rw-r--r-- | testcases/kernel/syscalls/faccessat2/faccessat201.c | 88 | ||||
-rw-r--r-- | testcases/kernel/syscalls/faccessat2/faccessat202.c | 102 |
4 files changed, 201 insertions, 0 deletions
diff --git a/testcases/kernel/syscalls/faccessat2/.gitignore b/testcases/kernel/syscalls/faccessat2/.gitignore new file mode 100644 index 000000000..f58f045f4 --- /dev/null +++ b/testcases/kernel/syscalls/faccessat2/.gitignore @@ -0,0 +1,2 @@ +/faccessat201 +/faccessat202 diff --git a/testcases/kernel/syscalls/faccessat2/Makefile b/testcases/kernel/syscalls/faccessat2/Makefile new file mode 100644 index 000000000..aaac6b703 --- /dev/null +++ b/testcases/kernel/syscalls/faccessat2/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2023 FUJITSU LIMITED. All rights reserved. +# Author: Yang Xu <xuyang2018.jy@fujitsu.com> + +top_srcdir ?= ../../../.. + +include $(top_srcdir)/include/mk/testcases.mk + +include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/faccessat2/faccessat201.c b/testcases/kernel/syscalls/faccessat2/faccessat201.c new file mode 100644 index 000000000..012091752 --- /dev/null +++ b/testcases/kernel/syscalls/faccessat2/faccessat201.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 FUJITSU LIMITED. All rights reserved. + * Copyright (c) Linux Test Project, 2003-2023 + * Author: Yang Xu <xuyang2018.jy@fujitsu.com> + */ + +/*\ + * [Description] + * + * Check the basic functionality of faccessat2(). + * + * Minimum Linux version required is v5.8. + */ + +#include <stdlib.h> + +#include "tst_test.h" +#include "lapi/syscalls.h" +#include "lapi/faccessat.h" + +#define TESTDIR "faccessat2dir" +#define TESTFILE "faccessat2file" +#define RELPATH "faccessat2dir/faccessat2file" +#define TESTSYMLINK "faccessat2symlink" + +static int dir_fd, bad_fd = -1; +static int atcwd_fd = AT_FDCWD; +static char *testfile; +static char *abs_path; +static char *rel_path; +static char *sym_path; + +static struct tcase { + int *fd; + char **filename; + int flags; +} tcases[] = { + {&dir_fd, &testfile, 0}, + {&bad_fd, &abs_path, 0}, + {&atcwd_fd, &rel_path, 0}, + {&dir_fd, &testfile, AT_EACCESS}, + {&bad_fd, &abs_path, AT_EACCESS}, + {&atcwd_fd, &rel_path, AT_EACCESS}, + {&atcwd_fd, &sym_path, AT_SYMLINK_NOFOLLOW}, +}; + +static void verify_faccessat2(unsigned int i) +{ + struct tcase *tc = &tcases[i]; + + TST_EXP_PASS(faccessat2(*tc->fd, *tc->filename, R_OK, tc->flags), + "faccessat2(%d, %s, R_OK, %d)", + *tc->fd, *tc->filename, tc->flags); +} + +static void setup(void) +{ + char *tmpdir_path = tst_get_tmpdir(); + + abs_path = tst_aprintf("%s/%s", tmpdir_path, RELPATH); + free(tmpdir_path); + + SAFE_MKDIR(TESTDIR, 0777); + dir_fd = SAFE_OPEN(TESTDIR, O_DIRECTORY); + SAFE_TOUCH(abs_path, 0444, NULL); + SAFE_SYMLINK(abs_path, TESTSYMLINK); +} + +static void cleanup(void) +{ + if (dir_fd > -1) + SAFE_CLOSE(dir_fd); +} + +static struct tst_test test = { + .test = verify_faccessat2, + .tcnt = ARRAY_SIZE(tcases), + .setup = setup, + .cleanup = cleanup, + .bufs = (struct tst_buffers []) { + {&testfile, .str = TESTFILE}, + {&rel_path, .str = RELPATH}, + {&sym_path, .str = TESTSYMLINK}, + {}, + }, + .needs_tmpdir = 1, +}; diff --git a/testcases/kernel/syscalls/faccessat2/faccessat202.c b/testcases/kernel/syscalls/faccessat2/faccessat202.c new file mode 100644 index 000000000..a60db2bf8 --- /dev/null +++ b/testcases/kernel/syscalls/faccessat2/faccessat202.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 FUJITSU LIMITED. All rights reserved. + * Copyright (c) Linux Test Project, 2003-2023 + * Author: Yang Xu <xuyang2018.jy@fujitsu.com> + */ + +/*\ + * [Description] + * + * Test basic error handling of faccessat2 syscall: + * + * - faccessat2() fails with EFAULT if pathname is a bad pathname point. + * - faccessat2() fails with EINVAL if flags is -1. + * - faccessat2() fails with EINVAL if mode is -1. + * - faccessat2() fails with EBADF if dirfd is -1. + * - faccessat2() fails with ENOTDIR if pathname is relative path to a + * file and dir_fd is file descriptor for this file. + * - faccessat2() fails with EACCES if flags is AT_EACCESS and not using + * the effective user and group IDs. + * + * Minimum Linux version required is v5.8. + */ + +#include <pwd.h> + +#include "tst_test.h" +#include "lapi/syscalls.h" +#include "lapi/faccessat.h" + +#define TESTUSER "nobody" +#define TESTDIR "faccessat2dir" +#define RELPATH "faccessat2dir/faccessat2file" + +static int fd; +static int bad_fd = -1; +static int atcwd_fd = AT_FDCWD; +static char *bad_path; +static char *rel_path; + +static struct passwd *ltpuser; + +static struct tcase { + int *fd; + char **filename; + int mode; + int flags; + int exp_errno; + const char *desc; +} tcases[] = { + {&atcwd_fd, &bad_path, R_OK, 0, EFAULT, "invalid address"}, + {&atcwd_fd, &rel_path, R_OK, -1, EINVAL, "invalid flags"}, + {&atcwd_fd, &rel_path, -1, 0, EINVAL, "invalid mode"}, + {&bad_fd, &rel_path, R_OK, 0, EBADF, "invalid fd"}, + {&fd, &rel_path, R_OK, 0, ENOTDIR, "fd pointing to file"}, + {&atcwd_fd, &rel_path, R_OK, AT_EACCESS, EACCES, + "AT_EACCESS and unprivileged EUID"}, +}; + +static void verify_faccessat2(unsigned int i) +{ + struct tcase *tc = &tcases[i]; + + if (tc->exp_errno == EACCES) + SAFE_SETEUID(ltpuser->pw_uid); + + TST_EXP_FAIL(faccessat2(*tc->fd, *tc->filename, tc->mode, tc->flags), + tc->exp_errno, "faccessat2() with %s", tc->desc); + + if (tc->exp_errno == EACCES) + SAFE_SETEUID(0); +} + +static void setup(void) +{ + SAFE_MKDIR(TESTDIR, 0666); + SAFE_TOUCH(RELPATH, 0444, NULL); + + fd = SAFE_OPEN(RELPATH, O_RDONLY); + bad_path = tst_get_bad_addr(NULL); + + ltpuser = SAFE_GETPWNAM(TESTUSER); +} + +static void cleanup(void) +{ + if (fd > -1) + SAFE_CLOSE(fd); +} + +static struct tst_test test = { + .test = verify_faccessat2, + .tcnt = ARRAY_SIZE(tcases), + .setup = setup, + .cleanup = cleanup, + .bufs = (struct tst_buffers []) { + {&rel_path, .str = RELPATH}, + {}, + }, + .needs_tmpdir = 1, + .needs_root = 1, +}; |