[PATCH v1] tests: extend coverage for fcntl options and flags
Zhibin Li
08826794brmt at gmail.com
Sun May 27 16:56:13 UTC 2018
* tests/fcntl64.c: Test short read of struct flock.
* tests/struct_flock.c: Likewise.
* tests/fcntl.c: Include assert.h.
(struct fcntl_cmd_check): New struct definition.
(print_retval_flags, test_set_cmd, test_get_cmd,
print_flags_getfd, print_flags_getfl, print_flags_getlease,
print_flags_getseals, print_flags_getsig, test_fcntl): New functions.
(main): Use test_fcntl.
---
tests/fcntl.c | 226 +++++++++++++++++++++++++++++++++++++++++++++++++++
tests/fcntl64.c | 20 +++--
tests/struct_flock.c | 20 +++--
3 files changed, 252 insertions(+), 14 deletions(-)
diff --git a/tests/fcntl.c b/tests/fcntl.c
index 45c20d9d..7999f81f 100644
--- a/tests/fcntl.c
+++ b/tests/fcntl.c
@@ -28,6 +28,7 @@
#include "tests.h"
#include <asm/unistd.h>
+#include <assert.h>
#ifdef __NR_fcntl
@@ -67,6 +68,9 @@ test_flock64(void)
#if !defined(F_SETOWN_EX) || F_SETOWN_EX != F_GETLK64
TEST_FLOCK64_EINVAL(F_GETLK64);
#endif
+#ifdef F_OFD_GETLK
+ TEST_FLOCK64_EINVAL(F_OFD_GETLK);
+#endif
}
/*
@@ -137,6 +141,227 @@ test_f_owner_ex(void)
}
#endif /* TEST_F_OWNER_EX */
+struct fcntl_cmd_check {
+ int fd;
+ int cmd;
+ const char *cmd_str;
+ int arg;
+ const char *arg_str;
+ void (*print_flags)(long rc);
+};
+
+static void
+print_retval_flags(const struct fcntl_cmd_check *check, long rc)
+{
+ if (check->print_flags) {
+ check->print_flags(rc);
+ } else {
+ printf("%s", sprintrc(rc));
+ }
+ printf("\n");
+}
+
+static void
+test_set_cmd(const struct fcntl_cmd_check *check)
+{
+ long rc = syscall(TEST_SYSCALL_NR, check->fd, check->cmd, check->arg);
+ printf("%s(%d, %s, %s) = %s\n",
+ TEST_SYSCALL_STR, check->fd, check->cmd_str,
+ check->arg_str, sprintrc(rc));
+
+ /*bad file fd*/
+ syscall(TEST_SYSCALL_NR, -1, check->cmd, check->arg);
+ printf("%s(-1, %s, %s) = -1 EBADF (Bad file descriptor)\n",
+ TEST_SYSCALL_STR, check->cmd_str, check->arg_str);
+}
+
+static void
+test_get_cmd(const struct fcntl_cmd_check *check)
+{
+ long rc = syscall(TEST_SYSCALL_NR, check->fd, check->cmd);
+ printf("%s(%d, %s) = ",
+ TEST_SYSCALL_STR, check->fd, check->cmd_str);
+ print_retval_flags(check, rc);
+
+ /*bad file fd*/
+ syscall(TEST_SYSCALL_NR, -1, check->cmd);
+ printf("%s(-1, %s) = -1 EBADF (Bad file descriptor)\n",
+ TEST_SYSCALL_STR, check->cmd_str);
+}
+
+static void
+print_flags_getfd(long rc)
+{
+ assert(rc >= 0);
+ const char *text;
+ text = rc & 1 ? " (flags FD_CLOEXEC)" : "";
+ printf("%#lx%s", rc, text);
+}
+
+static void
+print_flags_getfl(long rc)
+{
+ assert(rc >= 0);
+ const char *text;
+
+ switch (rc) {
+ case 00:
+ text = "O_RDONLY";
+ break;
+ case 01:
+ text = "O_WRONLY";
+ break;
+ case 02:
+ text = "O_RDWR";
+ break;
+ case 0100000|00:
+ text = "O_RDONLY|O_LARGEFILE";
+ break;
+ case 0100000|01:
+ text = "O_WRONLY|O_LARGEFILE";
+ break;
+ case 0100000|02:
+ text = "O_RDWR|O_LARGEFILE";
+ break;
+ default:
+ error_msg_and_fail("fcntl returned %#lx, does the"
+ " test have to be updated?", rc);
+ }
+ printf("%#lx (flags %s)", rc, text);
+}
+
+static void
+print_flags_getlease(long rc)
+{
+ assert(rc >= 0);
+ const char *text;
+
+ switch (rc) {
+ case 0:
+ text = "F_RDLCK";
+ break;
+ case 1:
+ text = "F_WRLCK";
+ break;
+ case 2:
+ text = "F_UNLCK";
+ break;
+ default:
+ error_msg_and_fail("fcntl returned %#lx, does the"
+ " test have to be updated?", rc);
+ }
+ printf("%#lx (%s)", rc, text);
+}
+
+#ifdef HAVE_LINUX_MEMFD_H
+static void
+print_flags_getseals(long rc)
+{
+ assert(rc >= 0);
+ const char *text;
+ if (!rc) {
+ text = "";
+ printf("%ld", rc);
+ } else {
+ switch (rc) {
+ case 0x0001:
+ text = "F_SEAL_SEAL";
+ break;
+ case 0x0002:
+ text = "F_SEAL_SHRINK";
+ break;
+ case 0x0004:
+ text = "F_SEAL_GROW";
+ break;
+ case 0x0008:
+ text = "F_SEAL_WRITE";
+ break;
+ default:
+ error_msg_and_fail("fcntl returned %#lx, does the"
+ " test have to be updated?", rc);
+ }
+ printf("%#lx (seals %s)", rc, text);
+ }
+}
+#endif
+
+static void
+print_flags_getsig(long rc)
+{
+ assert(rc >= 0);
+ const char *text;
+
+ if (!rc) {
+ text = "";
+ printf("%ld", rc);
+ } else {
+ switch (rc) {
+ case 1:
+ text = "SIGHUP";
+ break;
+ default:
+ error_msg_and_fail("fcntl returned %#lx, does the"
+ " test have to be updated?", rc);
+ }
+ printf("%ld (%s)", rc, text);
+ }
+}
+
+static void
+test_fcntl(void)
+{
+#ifdef __NR_memfd_create
+
+# ifdef HAVE_LINUX_MEMFD_H
+# include <linux/memfd.h>
+# endif
+ int memfd = syscall(__NR_memfd_create, "seal.sample", MFD_ALLOW_SEALING);
+ struct fcntl_cmd_check check_seals[] = {
+ { memfd, ARG_STR(F_ADD_SEALS),
+ ARG_STR(0) },
+ { memfd, ARG_STR(F_ADD_SEALS),
+ ARG_STR(F_SEAL_SEAL) },
+ { memfd, ARG_STR(F_GET_SEALS),
+ .print_flags = print_flags_getseals} };
+ test_set_cmd(&check_seals[0]);
+ test_get_cmd(&check_seals[2]);
+ test_set_cmd(&check_seals[1]);
+ test_get_cmd(&check_seals[2]);
+#endif
+ static const struct fcntl_cmd_check set_checks[] = {
+ { 0, ARG_STR(F_SETFD), ARG_STR(FD_CLOEXEC) },
+ { 0, ARG_STR(F_SETOWN), ARG_STR(20) },
+ { 0, ARG_STR(F_SETPIPE_SZ), ARG_STR(4097) },
+ { 0, ARG_STR(F_DUPFD), ARG_STR(0) },
+ { 0, ARG_STR(F_DUPFD_CLOEXEC), ARG_STR(0) },
+ { 0, ARG_STR(F_SETFL), ARG_STR(O_RDWR|O_LARGEFILE) },
+ { 0, ARG_STR(F_NOTIFY), ARG_STR(DN_ACCESS) },
+ { 1, ARG_STR(F_SETLEASE), ARG_STR(F_RDLCK) },
+ { 0, ARG_STR(F_SETSIG), 0, "SIG_0" },
+ { 1, ARG_STR(F_SETSIG), 1, "SIGHUP" }
+ };
+
+ static const struct fcntl_cmd_check get_checks[] = {
+ { 0, ARG_STR(F_GETFD), .print_flags = print_flags_getfd },
+ { 1, ARG_STR(F_GETFD), .print_flags = print_flags_getfd },
+ { 0, ARG_STR(F_GETOWN) },
+ { 0, ARG_STR(F_GETPIPE_SZ) },
+ { 0, ARG_STR(F_GETFL), .print_flags = print_flags_getfl },
+ { 1, ARG_STR(F_GETLEASE), .print_flags = print_flags_getlease },
+ { 0, ARG_STR(F_GETSIG), .print_flags = print_flags_getsig },
+ { 1, ARG_STR(F_GETSIG), .print_flags = print_flags_getsig }
+ };
+
+ for (unsigned int i = 0; i < ARRAY_SIZE(set_checks); i++) {
+ test_set_cmd(set_checks + i);
+ }
+
+ for (unsigned int j = 0; j < ARRAY_SIZE(get_checks); j++) {
+ test_get_cmd(get_checks + j);
+ }
+
+}
+
int
main(void)
{
@@ -146,6 +371,7 @@ main(void)
#ifdef TEST_F_OWNER_EX
test_f_owner_ex();
#endif
+ test_fcntl();
puts("+++ exited with 0 +++");
return 0;
diff --git a/tests/fcntl64.c b/tests/fcntl64.c
index 068956ed..c7da0a44 100644
--- a/tests/fcntl64.c
+++ b/tests/fcntl64.c
@@ -40,15 +40,21 @@
static void
test_flock64_einval(const int cmd, const char *name)
{
- struct_kernel_flock64 fl = {
- .l_type = F_RDLCK,
- .l_start = 0xdefaced1facefeedULL,
- .l_len = 0xdefaced2cafef00dULL
- };
- long rc = invoke_test_syscall(cmd, &fl);
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct_kernel_flock64, fl);
+ fl->l_type = F_RDLCK;
+ fl->l_whence = SEEK_SET;
+ fl->l_start = 0xdefaced1facefeedULL;
+ fl->l_len = 0xdefaced2cafef00dULL;
+ long rc;
+ rc = invoke_test_syscall(cmd, fl);
printf("%s(0, %s, {l_type=F_RDLCK, l_whence=SEEK_SET"
", l_start=%jd, l_len=%jd}) = %s\n", TEST_SYSCALL_STR, name,
- (intmax_t) fl.l_start, (intmax_t) fl.l_len, sprintrc(rc));
+ (intmax_t) fl->l_start, (intmax_t) fl->l_len, sprintrc(rc));
+
+ void *bad_addr = (void *) fl + 1;
+ rc = invoke_test_syscall(cmd, bad_addr);
+ printf("%s(0, %s, %p) = %s\n",
+ TEST_SYSCALL_STR, name, bad_addr, sprintrc(rc));
}
static void
diff --git a/tests/struct_flock.c b/tests/struct_flock.c
index 428c038d..3c5007fa 100644
--- a/tests/struct_flock.c
+++ b/tests/struct_flock.c
@@ -54,15 +54,21 @@ invoke_test_syscall(const unsigned int cmd, void *const p)
static void
test_flock_einval(const int cmd, const char *name)
{
- struct_kernel_flock fl = {
- .l_type = F_RDLCK,
- .l_start = (TYPEOF_FLOCK_OFF_T) 0xdefaced1facefeedULL,
- .l_len = (TYPEOF_FLOCK_OFF_T) 0xdefaced2cafef00dULL
- };
- long rc = invoke_test_syscall(cmd, &fl);
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct_kernel_flock, fl);
+ fl->l_type = F_RDLCK;
+ fl->l_whence = SEEK_SET;
+ fl->l_start = (TYPEOF_FLOCK_OFF_T) 0xdefaced1facefeedULL;
+ fl->l_len = (TYPEOF_FLOCK_OFF_T) 0xdefaced2cafef00dULL;
+ long rc;
+ rc = invoke_test_syscall(cmd, fl);
printf("%s(0, %s, {l_type=F_RDLCK, l_whence=SEEK_SET"
", l_start=%jd, l_len=%jd}) = %s\n", TEST_SYSCALL_STR, name,
- (intmax_t) fl.l_start, (intmax_t) fl.l_len, sprintrc(rc));
+ (intmax_t) fl->l_start, (intmax_t) fl->l_len, sprintrc(rc));
+
+ void *bad_addr = (void *) fl + 1;
+ rc = invoke_test_syscall(cmd, bad_addr);
+ printf("%s(0, %s, %p) = %s\n",
+ TEST_SYSCALL_STR, name, bad_addr, sprintrc(rc));
}
static void
--
2.14.3
More information about the Strace-devel
mailing list