[LTP] [PATCH] syscalls/openat2: New tests
Viresh Kumar
viresh.kumar@linaro.org
Fri Feb 28 11:50:23 CET 2020
Add tests to check working of openat2() syscall.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
configure.ac | 1 +
include/lapi/openat2.h | 66 ++++++++++++++
runtest/syscalls | 3 +
testcases/kernel/syscalls/openat2/.gitignore | 2 +
testcases/kernel/syscalls/openat2/Makefile | 9 ++
testcases/kernel/syscalls/openat2/openat201.c | 87 +++++++++++++++++++
testcases/kernel/syscalls/openat2/openat202.c | 62 +++++++++++++
7 files changed, 230 insertions(+)
create mode 100644 include/lapi/openat2.h
create mode 100644 testcases/kernel/syscalls/openat2/.gitignore
create mode 100644 testcases/kernel/syscalls/openat2/Makefile
create mode 100644 testcases/kernel/syscalls/openat2/openat201.c
create mode 100644 testcases/kernel/syscalls/openat2/openat202.c
diff --git a/configure.ac b/configure.ac
index c9ec39fce2df..238d1cde85f2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -96,6 +96,7 @@ AC_CHECK_FUNCS([ \
name_to_handle_at \
open_tree \
openat \
+ openat2 \
pidfd_open \
pidfd_send_signal \
pkey_mprotect \
diff --git a/include/lapi/openat2.h b/include/lapi/openat2.h
new file mode 100644
index 000000000000..2212a84c4d93
--- /dev/null
+++ b/include/lapi/openat2.h
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2020 Linaro Limited. All rights reserved.
+ * Author: Viresh Kumar <viresh.kumar@linaro.org>
+ */
+
+#ifndef OPENAT2_H
+#define OPENAT2_H
+
+#include <sys/syscall.h>
+#include <linux/types.h>
+
+#include "lapi/syscalls.h"
+
+#include "config.h"
+
+#ifndef HAVE_OPENAT2
+/*
+ * Arguments for how openat2(2) should open the target path. If only @flags and
+ * @mode are non-zero, then openat2(2) operates very similarly to openat(2).
+ *
+ * However, unlike openat(2), unknown or invalid bits in @flags result in
+ * -EINVAL rather than being silently ignored. @mode must be zero unless one of
+ * {O_CREAT, O_TMPFILE} are set.
+ *
+ * @flags: O_* flags.
+ * @mode: O_CREAT/O_TMPFILE file mode.
+ * @resolve: RESOLVE_* flags.
+ */
+struct open_how {
+ __u64 flags;
+ __u64 mode;
+ __u64 resolve;
+};
+
+/* how->resolve flags for openat2(2). */
+#define RESOLVE_NO_XDEV 0x01 /* Block mount-point crossings
+ (includes bind-mounts). */
+#define RESOLVE_NO_MAGICLINKS 0x02 /* Block traversal through procfs-style
+ "magic-links". */
+#define RESOLVE_NO_SYMLINKS 0x04 /* Block traversal through all symlinks
+ (implies OEXT_NO_MAGICLINKS) */
+#define RESOLVE_BENEATH 0x08 /* Block "lexical" trickery like
+ "..", symlinks, and absolute
+ paths which escape the dirfd. */
+#define RESOLVE_IN_ROOT 0x10 /* Make all jumps to "/" and ".."
+ be scoped inside the dirfd
+ (similar to chroot(2)). */
+
+int openat2(int dfd, const char *pathname, struct open_how *how, size_t size)
+{
+ return tst_syscall(__NR_openat2, dfd, pathname, how, size);
+}
+#endif
+
+void openat2_supported_by_kernel(void)
+{
+ if ((tst_kvercmp(5, 6, 0)) < 0) {
+ /* Check if the syscall is backported on an older kernel */
+ TEST(syscall(__NR_openat2, -1, NULL, NULL, 0));
+ if (TST_RET == -1 && TST_ERR == ENOSYS)
+ tst_brk(TCONF, "Test not supported on kernel version < v5.2");
+ }
+}
+
+#endif /* OPENAT2_H */
diff --git a/runtest/syscalls b/runtest/syscalls
index 14df8d34338e..b85ba83a4095 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -845,6 +845,9 @@ openat01 openat01
openat02 openat02
openat03 openat03
+openat201 openat201
+openat202 openat202
+
open_tree01 open_tree01
open_tree02 open_tree02
diff --git a/testcases/kernel/syscalls/openat2/.gitignore b/testcases/kernel/syscalls/openat2/.gitignore
new file mode 100644
index 000000000000..3da61e6e40c1
--- /dev/null
+++ b/testcases/kernel/syscalls/openat2/.gitignore
@@ -0,0 +1,2 @@
+openat201
+openat202
diff --git a/testcases/kernel/syscalls/openat2/Makefile b/testcases/kernel/syscalls/openat2/Makefile
new file mode 100644
index 000000000000..c26cffd37f39
--- /dev/null
+++ b/testcases/kernel/syscalls/openat2/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+top_srcdir ?= ../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+
+LDLIBS += $(AIO_LIBS)
+
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/openat2/openat201.c b/testcases/kernel/syscalls/openat2/openat201.c
new file mode 100644
index 000000000000..b35cea6725b3
--- /dev/null
+++ b/testcases/kernel/syscalls/openat2/openat201.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2020 Viresh Kumar <viresh.kumar@linaro.org>
+ *
+ * Basic openat2() test.
+ */
+#include "tst_test.h"
+#include "lapi/openat2.h"
+
+#define TEST_FILE "test_file"
+#define TEST_DIR "test_dir"
+
+static int dir_fd = -1, fd_atcwd = AT_FDCWD;
+
+static struct tcase {
+ int *dfd;
+ const char *pathname;
+ __u64 flags;
+ __u64 mode;
+ __u64 resolve;
+} tcases[] = {
+ {&dir_fd, TEST_FILE, O_RDWR, S_IRWXU, 0},
+ {&dir_fd, TEST_FILE, O_RDONLY, S_IRUSR, 0},
+ {&dir_fd, TEST_FILE, O_WRONLY, S_IWUSR, 0},
+ {&dir_fd, TEST_FILE, O_RDWR, S_IRWXU, RESOLVE_NO_XDEV},
+ {&dir_fd, TEST_FILE, O_RDWR, S_IRWXU, RESOLVE_NO_MAGICLINKS},
+ {&dir_fd, TEST_FILE, O_RDWR, S_IRWXU, RESOLVE_NO_SYMLINKS},
+ {&dir_fd, TEST_FILE, O_RDWR, S_IRWXU, RESOLVE_BENEATH},
+ {&dir_fd, TEST_FILE, O_RDWR, S_IRWXU, RESOLVE_IN_ROOT},
+ {&fd_atcwd, TEST_FILE, O_RDWR, S_IRWXU, 0},
+ {&fd_atcwd, TEST_FILE, O_RDONLY, S_IRUSR, 0},
+ {&fd_atcwd, TEST_FILE, O_WRONLY, S_IWUSR, 0},
+ {&fd_atcwd, TEST_FILE, O_RDWR, S_IRWXU, RESOLVE_NO_XDEV},
+ {&fd_atcwd, TEST_FILE, O_RDWR, S_IRWXU, RESOLVE_NO_MAGICLINKS},
+ {&fd_atcwd, TEST_FILE, O_RDWR, S_IRWXU, RESOLVE_NO_SYMLINKS},
+ {&fd_atcwd, TEST_FILE, O_RDWR, S_IRWXU, RESOLVE_BENEATH},
+ {&fd_atcwd, TEST_FILE, O_RDWR, S_IRWXU, RESOLVE_IN_ROOT},
+};
+
+static void cleanup(void)
+{
+ if (dir_fd != -1)
+ SAFE_CLOSE(dir_fd);
+}
+
+static void setup(void)
+{
+ openat2_supported_by_kernel();
+
+ SAFE_MKDIR(TEST_DIR, 0700);
+ dir_fd = SAFE_OPEN(TEST_DIR, O_DIRECTORY);
+}
+
+static void run(unsigned int n)
+{
+ int fd;
+ struct stat file_stat;
+ struct tcase *tc = &tcases[n];
+ struct open_how how = {
+ .flags = tc->flags | O_CREAT,
+ .mode = tc->mode,
+ .resolve = tc->resolve
+ };
+
+ TEST(fd = openat2(*tc->dfd, tc->pathname, &how, sizeof(how)));
+ if (fd == -1) {
+ tst_res(TFAIL | TTERRNO, "openat2() failed (%d)", n);
+ return;
+ }
+
+ SAFE_FSTAT(fd, &file_stat);
+
+ if (file_stat.st_size == 0)
+ tst_res(TPASS, "openat2() passed (%d)", n);
+ else
+ tst_res(TFAIL, "fstat() didn't work as expected (%d)", n);
+
+ SAFE_CLOSE(fd);
+}
+
+static struct tst_test test = {
+ .tcnt = ARRAY_SIZE(tcases),
+ .test = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .needs_tmpdir = 1,
+};
diff --git a/testcases/kernel/syscalls/openat2/openat202.c b/testcases/kernel/syscalls/openat2/openat202.c
new file mode 100644
index 000000000000..aef2246d098d
--- /dev/null
+++ b/testcases/kernel/syscalls/openat2/openat202.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2020 Viresh Kumar <viresh.kumar@linaro.org>
+ *
+ * Basic openat2() test to check various failures.
+ */
+#include "tst_test.h"
+#include "lapi/openat2.h"
+
+#define TEST_FILE "test_file"
+#define TEST_DIR "test_dir"
+
+static struct tcase {
+ int dfd;
+ const char *pathname;
+ __u64 flags;
+ __u64 mode;
+ __u64 resolve;
+ size_t size;
+ int exp_errno;
+} tcases[] = {
+ {-1, TEST_FILE, O_RDWR | O_CREAT, S_IRWXU, 0, sizeof(struct open_how), EBADF},
+ {AT_FDCWD, NULL, O_RDONLY | O_CREAT, S_IRUSR, 0, sizeof(struct open_how), EFAULT},
+ {AT_FDCWD, TEST_FILE, O_RDONLY, S_IWUSR, 0, sizeof(struct open_how), EINVAL},
+ {AT_FDCWD, TEST_FILE, O_RDWR | O_CREAT, -1, 0, sizeof(struct open_how), EINVAL},
+ {AT_FDCWD, TEST_FILE, O_RDWR | O_CREAT, S_IRWXU, -1, sizeof(struct open_how), EINVAL},
+ {AT_FDCWD, TEST_FILE, O_RDWR | O_CREAT, S_IRWXU, 0, 0, EINVAL},
+ {AT_FDCWD, TEST_FILE, O_RDWR | O_CREAT, S_IRWXU, 0, 2 * sizeof(struct open_how), E2BIG},
+};
+
+static void run(unsigned int n)
+{
+ struct tcase *tc = &tcases[n];
+ struct open_how how = {
+ .flags = tc->flags,
+ .mode = tc->mode,
+ .resolve = tc->resolve
+ };
+
+ TEST(openat2(tc->dfd, tc->pathname, &how, tc->size));
+
+ if (TST_RET != -1) {
+ SAFE_CLOSE(TST_RET);
+ tst_res(TFAIL, "openat2() passed unexpectedly (%d)", n);
+ return;
+ }
+
+ if (tc->exp_errno != TST_ERR) {
+ tst_res(TFAIL | TTERRNO, "openat2() should fail with %s (%d)",
+ tst_strerrno(tc->exp_errno), n);
+ return;
+ }
+
+ tst_res(TPASS | TTERRNO, "openat2() failed as expected (%d)", n);
+}
+
+static struct tst_test test = {
+ .tcnt = ARRAY_SIZE(tcases),
+ .test = run,
+ .setup = openat2_supported_by_kernel,
+ .needs_tmpdir = 1,
+};
--
2.21.0.rc0.269.g1a574e7a288b
More information about the ltp
mailing list