All of lore.kernel.org
 help / color / mirror / Atom feed
* [LTP] [PATCH v2 0/6] Added memfd_create() testsuite
@ 2017-03-06 17:45 Jakub Racek
  2017-03-06 17:45 ` [LTP] [PATCH v2 1/6] Added syscall numbers for memfd_create Jakub Racek
                   ` (5 more replies)
  0 siblings, 6 replies; 12+ messages in thread
From: Jakub Racek @ 2017-03-06 17:45 UTC (permalink / raw)
  To: ltp

memfd_create() is a syscall that creates an anonymous file. This syscall was
originally introduced in "File Sealing & memfd_create()" patchset by
David Herrmann <dh.herrmann@gmail.com>.
My patchset is a partial port of memfd_create() testsuite to LTP, with lapi
extended as necessary.
This is a V2 patchset. V1 was originally posted on 28/02/2017, but it had
LTP style problems and didn't include syscall numbers.
Code that runs _dup, _mmap and _open tests in multi-threaded environment was
not ported yet.

Jakub Racek (6):
  Added syscall numbers for memfd_create
  Added memfd_create() lapi flags
  Added fcntl() lapi flags
  Added fallocate() flags and wrapper to lapi
  syscalls: added memfd_create dir and memfd_create/memfd_create01.c
  syscalls/memfd_create02.c: added new test

 include/lapi/fallocate.h                           |  66 +++
 include/lapi/fcntl.h                               |  25 +
 include/lapi/memfd.h                               |  27 ++
 runtest/syscalls                                   |   3 +
 testcases/kernel/include/aarch64.in                |   1 +
 testcases/kernel/include/arm.in                    |   1 +
 testcases/kernel/include/hppa.in                   |   1 +
 testcases/kernel/include/i386.in                   |   1 +
 testcases/kernel/include/ia64.in                   |   1 +
 testcases/kernel/include/powerpc.in                |   1 +
 testcases/kernel/include/powerpc64.in              |   1 +
 testcases/kernel/include/s390.in                   |   1 +
 testcases/kernel/include/s390x.in                  |   1 +
 testcases/kernel/include/sh.in                     |   1 +
 testcases/kernel/include/sparc.in                  |   1 +
 testcases/kernel/include/sparc64.in                |   1 +
 testcases/kernel/include/x86_64.in                 |   1 +
 testcases/kernel/syscalls/.gitignore               |   2 +
 testcases/kernel/syscalls/memfd_create/Makefile    |  19 +
 .../kernel/syscalls/memfd_create/memfd_create01.c  | 303 ++++++++++++
 .../kernel/syscalls/memfd_create/memfd_create02.c  |  92 ++++
 .../syscalls/memfd_create/memfd_create_common.h    | 525 +++++++++++++++++++++
 22 files changed, 1075 insertions(+)
 create mode 100644 include/lapi/fallocate.h
 create mode 100644 include/lapi/memfd.h
 create mode 100644 testcases/kernel/syscalls/memfd_create/Makefile
 create mode 100644 testcases/kernel/syscalls/memfd_create/memfd_create01.c
 create mode 100644 testcases/kernel/syscalls/memfd_create/memfd_create02.c
 create mode 100644 testcases/kernel/syscalls/memfd_create/memfd_create_common.h

-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [LTP] [PATCH v2 1/6] Added syscall numbers for memfd_create
  2017-03-06 17:45 [LTP] [PATCH v2 0/6] Added memfd_create() testsuite Jakub Racek
@ 2017-03-06 17:45 ` Jakub Racek
  2017-03-06 17:45 ` [LTP] [PATCH v2 2/6] Added memfd_create() lapi flags Jakub Racek
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Jakub Racek @ 2017-03-06 17:45 UTC (permalink / raw)
  To: ltp

Signed-off-by: Jakub Racek <jracek@redhat.com>
---
 testcases/kernel/include/aarch64.in   | 1 +
 testcases/kernel/include/arm.in       | 1 +
 testcases/kernel/include/hppa.in      | 1 +
 testcases/kernel/include/i386.in      | 1 +
 testcases/kernel/include/ia64.in      | 1 +
 testcases/kernel/include/powerpc.in   | 1 +
 testcases/kernel/include/powerpc64.in | 1 +
 testcases/kernel/include/s390.in      | 1 +
 testcases/kernel/include/s390x.in     | 1 +
 testcases/kernel/include/sh.in        | 1 +
 testcases/kernel/include/sparc.in     | 1 +
 testcases/kernel/include/sparc64.in   | 1 +
 testcases/kernel/include/x86_64.in    | 1 +
 13 files changed, 13 insertions(+)

diff --git a/testcases/kernel/include/aarch64.in b/testcases/kernel/include/aarch64.in
index cb3fe06..b81c068 100644
--- a/testcases/kernel/include/aarch64.in
+++ b/testcases/kernel/include/aarch64.in
@@ -255,3 +255,4 @@ setns 268
 sendmmsg 269
 kcmp 272
 getrandom 278
+memfd_create 279
diff --git a/testcases/kernel/include/arm.in b/testcases/kernel/include/arm.in
index cee9718..0a5dde1 100644
--- a/testcases/kernel/include/arm.in
+++ b/testcases/kernel/include/arm.in
@@ -338,3 +338,4 @@ sched_setattr (__NR_SYSCALL_BASE+380)
 sched_getattr (__NR_SYSCALL_BASE+381)
 renameat2 (__NR_SYSCALL_BASE+382)
 getrandom (__NR_SYSCALL_BASE+384)
+memfd_create (__NR_SYSCALL_BASE+385)
diff --git a/testcases/kernel/include/hppa.in b/testcases/kernel/include/hppa.in
index b784a2b..3946155 100644
--- a/testcases/kernel/include/hppa.in
+++ b/testcases/kernel/include/hppa.in
@@ -15,3 +15,4 @@ faccessat (__NR_openat + 12)
 splice 291
 tee 293
 vmsplice 294
+memfd_create 340
diff --git a/testcases/kernel/include/i386.in b/testcases/kernel/include/i386.in
index 1f1cade..42c5e3f 100644
--- a/testcases/kernel/include/i386.in
+++ b/testcases/kernel/include/i386.in
@@ -338,3 +338,4 @@ sched_setattr 351
 sched_getattr 352
 renameat2 354
 getrandom 355
+memfd_create 356
diff --git a/testcases/kernel/include/ia64.in b/testcases/kernel/include/ia64.in
index 846141f..dad25f4 100644
--- a/testcases/kernel/include/ia64.in
+++ b/testcases/kernel/include/ia64.in
@@ -294,3 +294,4 @@ fanotify_mark 1324
 prlimit64 1325
 renameat2 1338
 getrandom 1339
+memfd_create 1340
diff --git a/testcases/kernel/include/powerpc.in b/testcases/kernel/include/powerpc.in
index 5ca42a6..10a6e5d 100644
--- a/testcases/kernel/include/powerpc.in
+++ b/testcases/kernel/include/powerpc.in
@@ -345,3 +345,4 @@ sched_setattr 355
 sched_getattr 356
 renameat2 357
 getrandom 359
+memfd_create 360
diff --git a/testcases/kernel/include/powerpc64.in b/testcases/kernel/include/powerpc64.in
index 5ca42a6..10a6e5d 100644
--- a/testcases/kernel/include/powerpc64.in
+++ b/testcases/kernel/include/powerpc64.in
@@ -345,3 +345,4 @@ sched_setattr 355
 sched_getattr 356
 renameat2 357
 getrandom 359
+memfd_create 360
diff --git a/testcases/kernel/include/s390.in b/testcases/kernel/include/s390.in
index afe94f5..770db7f 100644
--- a/testcases/kernel/include/s390.in
+++ b/testcases/kernel/include/s390.in
@@ -329,3 +329,4 @@ sched_setattr 345
 sched_getattr 346
 renameat2 347
 getrandom 349
+memfd_create 350
diff --git a/testcases/kernel/include/s390x.in b/testcases/kernel/include/s390x.in
index afe94f5..770db7f 100644
--- a/testcases/kernel/include/s390x.in
+++ b/testcases/kernel/include/s390x.in
@@ -329,3 +329,4 @@ sched_setattr 345
 sched_getattr 346
 renameat2 347
 getrandom 349
+memfd_create 350
diff --git a/testcases/kernel/include/sh.in b/testcases/kernel/include/sh.in
index 3cb7e21..0345f8d 100644
--- a/testcases/kernel/include/sh.in
+++ b/testcases/kernel/include/sh.in
@@ -362,3 +362,4 @@ fanotify_init 367
 fanotify_mark 368
 prlimit64 369
 kcmp 378
+memfd_create 385
diff --git a/testcases/kernel/include/sparc.in b/testcases/kernel/include/sparc.in
index f266777..b84c844 100644
--- a/testcases/kernel/include/sparc.in
+++ b/testcases/kernel/include/sparc.in
@@ -334,3 +334,4 @@ prlimit64 331
 kcmp 341
 renameat2 345
 getrandom 347
+memfd_create 348
diff --git a/testcases/kernel/include/sparc64.in b/testcases/kernel/include/sparc64.in
index cb91828..7e0be30 100644
--- a/testcases/kernel/include/sparc64.in
+++ b/testcases/kernel/include/sparc64.in
@@ -310,3 +310,4 @@ prlimit64 331
 kcmp 341
 renameat2 345
 getrandom 347
+memfd_create 348
diff --git a/testcases/kernel/include/x86_64.in b/testcases/kernel/include/x86_64.in
index f54abf4..dec7742 100644
--- a/testcases/kernel/include/x86_64.in
+++ b/testcases/kernel/include/x86_64.in
@@ -305,3 +305,4 @@ sched_setattr 314
 sched_getattr 315
 renameat2 316
 getrandom 318
+memfd_create 319
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [LTP] [PATCH v2 2/6] Added memfd_create() lapi flags
  2017-03-06 17:45 [LTP] [PATCH v2 0/6] Added memfd_create() testsuite Jakub Racek
  2017-03-06 17:45 ` [LTP] [PATCH v2 1/6] Added syscall numbers for memfd_create Jakub Racek
@ 2017-03-06 17:45 ` Jakub Racek
  2017-03-06 17:45 ` [LTP] [PATCH v2 3/6] Added fcntl() " Jakub Racek
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Jakub Racek @ 2017-03-06 17:45 UTC (permalink / raw)
  To: ltp

Signed-off-by: Jakub Racek <jracek@redhat.com>
---
 include/lapi/memfd.h | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 include/lapi/memfd.h

diff --git a/include/lapi/memfd.h b/include/lapi/memfd.h
new file mode 100644
index 0000000..18ed40f
--- /dev/null
+++ b/include/lapi/memfd.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2017  Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef LAPI_MEMFD_H
+#define LAPI_MEMFD_H
+
+/* flags for memfd_create(2) (unsigned int) */
+#ifndef MFD_CLOEXEC
+# define MFD_CLOEXEC             0x0001U
+#endif
+#ifndef MFD_ALLOW_SEALING
+# define MFD_ALLOW_SEALING       0x0002U
+#endif
+
+#endif
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [LTP] [PATCH v2 3/6] Added fcntl() lapi flags
  2017-03-06 17:45 [LTP] [PATCH v2 0/6] Added memfd_create() testsuite Jakub Racek
  2017-03-06 17:45 ` [LTP] [PATCH v2 1/6] Added syscall numbers for memfd_create Jakub Racek
  2017-03-06 17:45 ` [LTP] [PATCH v2 2/6] Added memfd_create() lapi flags Jakub Racek
@ 2017-03-06 17:45 ` Jakub Racek
  2017-03-06 17:45 ` [LTP] [PATCH v2 4/6] Added fallocate() flags and wrapper to lapi Jakub Racek
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Jakub Racek @ 2017-03-06 17:45 UTC (permalink / raw)
  To: ltp

Signed-off-by: Jakub Racek <jracek@redhat.com>
---
 include/lapi/fcntl.h | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/include/lapi/fcntl.h b/include/lapi/fcntl.h
index 38e41ec..849439d 100644
--- a/include/lapi/fcntl.h
+++ b/include/lapi/fcntl.h
@@ -50,6 +50,31 @@
 # define F_GETPIPE_SZ 1032
 #endif
 
+/*
+ * Set/Get seals
+ */
+#ifndef F_ADD_SEALS
+# define F_ADD_SEALS     (1033)
+#endif
+
+#ifndef F_GET_SEALS
+# define F_GET_SEALS     (1034)
+#endif
+
+#ifndef F_SEAL_SEAL
+# define F_SEAL_SEAL     0x0001  /* prevent further seals from being set */
+#endif
+
+#ifndef F_SEAL_SHRINK
+# define F_SEAL_SHRINK   0x0002  /* prevent file from shrinking */
+#endif
+#ifndef F_SEAL_GROW
+# define F_SEAL_GROW     0x0004  /* prevent file from growing */
+#endif
+#ifndef F_SEAL_WRITE
+# define F_SEAL_WRITE    0x0008  /* prevent writes */
+#endif
+
 #ifndef F_OWNER_PGRP
 # define F_OWNER_PGRP 2
 #endif
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [LTP] [PATCH v2 4/6] Added fallocate() flags and wrapper to lapi
  2017-03-06 17:45 [LTP] [PATCH v2 0/6] Added memfd_create() testsuite Jakub Racek
                   ` (2 preceding siblings ...)
  2017-03-06 17:45 ` [LTP] [PATCH v2 3/6] Added fcntl() " Jakub Racek
@ 2017-03-06 17:45 ` Jakub Racek
  2017-03-07 11:44   ` Cyril Hrubis
  2017-03-06 17:45 ` [LTP] [PATCH v2 5/6] syscalls: added memfd_create dir and memfd_create/memfd_create01.c Jakub Racek
  2017-03-06 17:45 ` [LTP] [PATCH v2 6/6] syscalls/memfd_create02.c: added new test Jakub Racek
  5 siblings, 1 reply; 12+ messages in thread
From: Jakub Racek @ 2017-03-06 17:45 UTC (permalink / raw)
  To: ltp

Signed-off-by: Jakub Racek <jracek@redhat.com>
---
 include/lapi/fallocate.h | 66 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)
 create mode 100644 include/lapi/fallocate.h

diff --git a/include/lapi/fallocate.h b/include/lapi/fallocate.h
new file mode 100644
index 0000000..79d0b7b
--- /dev/null
+++ b/include/lapi/fallocate.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) International Business Machines  Corp., 2007
+ * Copyright (c) 2014 Fujitsu Ltd.
+ *
+ * This program is free software;  you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ *
+ */
+
+#ifndef FALLOCATE_H
+#define FALLOCATE_H
+
+#include <sys/types.h>
+#include <endian.h>
+#include "config.h"
+#include "lapi/abisize.h"
+#include "linux_syscall_numbers.h"
+
+#ifndef SEEK_HOLE
+# define SEEK_HOLE 4
+#endif
+
+#ifndef FALLOC_FL_KEEP_SIZE
+# define FALLOC_FL_KEEP_SIZE 0x01
+#endif
+
+#ifndef FALLOC_FL_PUNCH_HOLE
+# define FALLOC_FL_PUNCH_HOLE 0x02
+#endif
+
+#ifndef FALLOC_FL_COLLAPSE_RANGE
+# define FALLOC_FL_COLLAPSE_RANGE 0x08
+#endif
+
+#ifndef FALLOC_FL_ZERO_RANGE
+# define FALLOC_FL_ZERO_RANGE 0x10
+#endif
+
+#ifndef FALLOC_FL_INSERT_RANGE
+# define FALLOC_FL_INSERT_RANGE 0x20
+#endif
+
+#if !defined(HAVE_FALLOCATE)
+static inline long fallocate(int fd, int mode, loff_t offset, loff_t len)
+{
+	/* Deal with 32bit ABIs that have 64bit syscalls. */
+# if LTP_USE_64_ABI
+	return ltp_syscall(__NR_fallocate, fd, mode, offset, len);
+# else
+	return (long)ltp_syscall(__NR_fallocate, fd, mode,
+				 __LONG_LONG_PAIR((off_t) (offset >> 32),
+						  (off_t) offset),
+				 __LONG_LONG_PAIR((off_t) (len >> 32),
+						  (off_t) len));
+# endif
+}
+#endif
+
+#endif /* FALLOCATE_H */
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [LTP] [PATCH v2 5/6] syscalls: added memfd_create dir and memfd_create/memfd_create01.c
  2017-03-06 17:45 [LTP] [PATCH v2 0/6] Added memfd_create() testsuite Jakub Racek
                   ` (3 preceding siblings ...)
  2017-03-06 17:45 ` [LTP] [PATCH v2 4/6] Added fallocate() flags and wrapper to lapi Jakub Racek
@ 2017-03-06 17:45 ` Jakub Racek
  2017-03-07 12:17   ` Cyril Hrubis
  2017-03-06 17:45 ` [LTP] [PATCH v2 6/6] syscalls/memfd_create02.c: added new test Jakub Racek
  5 siblings, 1 reply; 12+ messages in thread
From: Jakub Racek @ 2017-03-06 17:45 UTC (permalink / raw)
  To: ltp

Signed-off-by: Jakub Racek <jracek@redhat.com>
---
 runtest/syscalls                                   |   2 +
 testcases/kernel/syscalls/.gitignore               |   1 +
 testcases/kernel/syscalls/memfd_create/Makefile    |  19 +
 .../kernel/syscalls/memfd_create/memfd_create01.c  | 303 ++++++++++++
 .../syscalls/memfd_create/memfd_create_common.h    | 525 +++++++++++++++++++++
 5 files changed, 850 insertions(+)
 create mode 100644 testcases/kernel/syscalls/memfd_create/Makefile
 create mode 100644 testcases/kernel/syscalls/memfd_create/memfd_create01.c
 create mode 100644 testcases/kernel/syscalls/memfd_create/memfd_create_common.h

diff --git a/runtest/syscalls b/runtest/syscalls
index 931a354..fd305ce 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1448,3 +1448,5 @@ futex_wake03 futex_wake03
 futex_wake04 futex_wake04
 futex_wait_bitset01 futex_wait_bitset01
 futex_wait_bitset02 futex_wait_bitset02
+
+memfd_create01 memfd_create01
diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore
index 9a4727c..915b1b9 100644
--- a/testcases/kernel/syscalls/.gitignore
+++ b/testcases/kernel/syscalls/.gitignore
@@ -1116,3 +1116,4 @@
 /fanotify/fanotify06
 /perf_event_open/perf_event_open01
 /perf_event_open/perf_event_open02
+/memfd_create/memfd_create01
diff --git a/testcases/kernel/syscalls/memfd_create/Makefile b/testcases/kernel/syscalls/memfd_create/Makefile
new file mode 100644
index 0000000..9dbc4b9
--- /dev/null
+++ b/testcases/kernel/syscalls/memfd_create/Makefile
@@ -0,0 +1,19 @@
+#
+#  Copyright (C) 2017  Red Hat, Inc.
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License as
+#  published by the Free Software Foundation; either version 2 of
+#  the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it would be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+
+top_srcdir		?= ../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/memfd_create/memfd_create01.c b/testcases/kernel/syscalls/memfd_create/memfd_create01.c
new file mode 100644
index 0000000..a950ce5
--- /dev/null
+++ b/testcases/kernel/syscalls/memfd_create/memfd_create01.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2017  Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+ /*
+  *  Based on Linux/tools/testing/selftests/memfd/memfd_test.c
+  *  by David Herrmann <dh.herrmann@gmail.com>
+  *
+  *  24/02/2017   Port to LTP    <jracek@redhat.com>
+  */
+
+#define _GNU_SOURCE
+
+#include "tst_test.h"
+#include "memfd_create_common.h"
+
+/*
+ * Do few basic sealing tests to see whether setting/retrieving seals works.
+ */
+static void test_basic(int fd)
+{
+	/* add basic seals */
+	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
+	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_SHRINK |
+			F_SEAL_WRITE));
+	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SHRINK |
+			F_SEAL_WRITE));
+
+	/* add them again */
+	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_SHRINK |
+			F_SEAL_WRITE));
+	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SHRINK |
+			F_SEAL_WRITE));
+
+	/* add more seals and seal against sealing */
+	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_GROW | F_SEAL_SEAL));
+	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SHRINK |
+			F_SEAL_GROW |
+			F_SEAL_WRITE |
+			F_SEAL_SEAL));
+
+	/* verify that sealing no longer works */
+	CHECK_RESULT(mfd_fail_add_seals(fd, F_SEAL_GROW));
+	CHECK_RESULT(mfd_fail_add_seals(fd, 0));
+
+	tst_res(TPASS, "%s", __func__);
+}
+
+/*
+ * Verify that no sealing is possible when memfd is created without
+ * MFD_ALLOW_SEALING flag.
+ */
+static void test_no_sealing_without_flag(int fd)
+{
+	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SEAL));
+	CHECK_RESULT(mfd_fail_add_seals(fd, F_SEAL_SHRINK |
+			F_SEAL_GROW |
+			F_SEAL_WRITE));
+	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SEAL));
+
+	tst_res(TPASS, "%s", __func__);
+}
+
+/*
+ * Test SEAL_WRITE
+ * Test whether SEAL_WRITE actually prevents modifications.
+ */
+static void test_seal_write(int fd)
+{
+	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
+	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_WRITE));
+	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_WRITE));
+
+	CHECK_RESULT(mfd_assert_read(fd));
+	CHECK_RESULT(mfd_fail_write(fd));
+	CHECK_RESULT(mfd_assert_shrink(fd));
+	CHECK_RESULT(mfd_assert_grow(fd));
+	CHECK_RESULT(mfd_fail_grow_write(fd));
+
+	tst_res(TPASS, "%s", __func__);
+}
+
+/*
+ * Test SEAL_SHRINK
+ * Test whether SEAL_SHRINK actually prevents shrinking
+ */
+static void test_seal_shrink(int fd)
+{
+	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
+	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_SHRINK));
+	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SHRINK));
+
+	CHECK_RESULT(mfd_assert_read(fd));
+	CHECK_RESULT(mfd_assert_write(fd));
+	CHECK_RESULT(mfd_fail_shrink(fd));
+	CHECK_RESULT(mfd_assert_grow(fd));
+	CHECK_RESULT(mfd_assert_grow_write(fd));
+
+	tst_res(TPASS, "%s", __func__);
+}
+
+/*
+ * Test SEAL_GROW
+ * Test whether SEAL_GROW actually prevents growing
+ */
+static void test_seal_grow(int fd)
+{
+	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
+	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_GROW));
+	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_GROW));
+
+	CHECK_RESULT(mfd_assert_read(fd));
+	CHECK_RESULT(mfd_assert_write(fd));
+	CHECK_RESULT(mfd_assert_shrink(fd));
+	CHECK_RESULT(mfd_fail_grow(fd));
+	CHECK_RESULT(mfd_fail_grow_write(fd));
+
+	tst_res(TPASS, "%s", __func__);
+}
+
+/*
+ * Test SEAL_SHRINK | SEAL_GROW
+ * Test whether SEAL_SHRINK | SEAL_GROW actually prevents resizing
+ */
+static void test_seal_resize(int fd)
+{
+	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
+	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW));
+	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW));
+
+	CHECK_RESULT(mfd_assert_read(fd));
+	CHECK_RESULT(mfd_assert_write(fd));
+	CHECK_RESULT(mfd_fail_shrink(fd));
+	CHECK_RESULT(mfd_fail_grow(fd));
+	CHECK_RESULT(mfd_fail_grow_write(fd));
+
+	tst_res(TPASS, "%s", __func__);
+}
+
+/*
+ * Test sharing via dup()
+ * Test that seals are shared between dupped FDs and they're all equal.
+ */
+static void test_share_dup(int fd)
+{
+	int fd2;
+
+	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
+
+	fd2 = SAFE_DUP(fd);
+	CHECK_RESULT(mfd_assert_has_seals(fd2, 0));
+
+	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_WRITE));
+	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_WRITE));
+	CHECK_RESULT(mfd_assert_has_seals(fd2, F_SEAL_WRITE));
+
+	CHECK_RESULT(mfd_assert_add_seals(fd2, F_SEAL_SHRINK));
+	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK));
+	CHECK_RESULT(mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK));
+
+	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_SEAL));
+	CHECK_RESULT(mfd_assert_has_seals(fd,
+		F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL));
+	CHECK_RESULT(mfd_assert_has_seals(fd2,
+		F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL));
+
+	CHECK_RESULT(mfd_fail_add_seals(fd, F_SEAL_GROW));
+	CHECK_RESULT(mfd_fail_add_seals(fd2, F_SEAL_GROW));
+	CHECK_RESULT(mfd_fail_add_seals(fd, F_SEAL_SEAL));
+	CHECK_RESULT(mfd_fail_add_seals(fd2, F_SEAL_SEAL));
+
+	SAFE_CLOSE(fd2);
+
+	CHECK_RESULT(mfd_fail_add_seals(fd, F_SEAL_GROW));
+
+	tst_res(TPASS, "%s", __func__);
+}
+
+/*
+ * Test sealing with active mmap()s
+ * Modifying seals is only allowed if no other mmap() refs exist.
+ */
+static void test_share_mmap(int fd)
+{
+	void *p;
+
+	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
+
+	/* shared/writable ref prevents sealing WRITE, but allows others */
+	p = SAFE_MMAP(NULL,
+			MFD_DEF_SIZE,
+			PROT_READ | PROT_WRITE,
+			MAP_SHARED,
+			fd,
+			0);
+	CHECK_RESULT(mfd_fail_add_seals(fd, F_SEAL_WRITE));
+	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
+	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_SHRINK));
+	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SHRINK));
+	SAFE_MUNMAP(p, MFD_DEF_SIZE);
+
+	/* readable ref allows sealing */
+	p = SAFE_MMAP(NULL,
+			MFD_DEF_SIZE,
+			PROT_READ,
+			MAP_PRIVATE,
+			fd,
+			0);
+	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_WRITE));
+	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK));
+	SAFE_MUNMAP(p, MFD_DEF_SIZE);
+
+	tst_res(TPASS, "%s", __func__);
+}
+
+/*
+ * Test sealing with open(/proc/self/fd/%d)
+ * Via /proc we can get access to a separate file-context for the same memfd.
+ * This is *not* like dup(), but like a real separate open(). Make sure the
+ * semantics are as expected and we correctly check for RDONLY / WRONLY / RDWR.
+ */
+static void test_share_open(int fd)
+{
+	int fd2;
+
+	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
+
+	fd2 = CHECK_RESULT(mfd_assert_open(fd, O_RDWR, 0));
+	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_WRITE));
+	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_WRITE));
+	CHECK_RESULT(mfd_assert_has_seals(fd2, F_SEAL_WRITE));
+
+	CHECK_RESULT(mfd_assert_add_seals(fd2, F_SEAL_SHRINK));
+	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK));
+	CHECK_RESULT(mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK));
+
+	SAFE_CLOSE(fd);
+	fd = CHECK_RESULT(mfd_assert_open(fd2, O_RDONLY, 0));
+
+	CHECK_RESULT(mfd_fail_add_seals(fd, F_SEAL_SEAL));
+	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK));
+	CHECK_RESULT(mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK));
+
+	SAFE_CLOSE(fd2);
+
+	tst_res(TPASS, "%s", __func__);
+}
+
+static const struct tcase {
+	int flags;
+	void (*func)(int fd);
+} tcases[] = {
+	{MFD_ALLOW_SEALING, &test_basic},
+	{0,                 &test_no_sealing_without_flag},
+
+	{MFD_ALLOW_SEALING, &test_seal_write},
+	{MFD_ALLOW_SEALING, &test_seal_shrink},
+	{MFD_ALLOW_SEALING, &test_seal_grow},
+	{MFD_ALLOW_SEALING, &test_seal_resize},
+
+	{MFD_ALLOW_SEALING, &test_share_dup},
+	{MFD_ALLOW_SEALING, &test_share_mmap},
+	{MFD_ALLOW_SEALING, &test_share_open},
+};
+
+static void verify_memfd_create(unsigned int n)
+{
+	const struct tcase *tc;
+
+	tc = &tcases[n];
+
+	TEST(mfd_assert_new(TCID, MFD_DEF_SIZE, tc->flags));
+	if (TEST_RETURN < 0)
+		tst_brk(TBROK | TERRNO, "memfd_create() failed unexpectedly");
+
+	tc->func(TEST_RETURN);
+
+	if (TEST_RETURN > 0)
+		SAFE_CLOSE(TEST_RETURN);
+}
+
+static void setup(void)
+{
+	ASSERT_HAVE_MEMFD_CREATE();
+}
+
+static struct tst_test test = {
+	.tid = "memfd_create01",
+	.test = verify_memfd_create,
+	.tcnt = ARRAY_SIZE(tcases),
+	.setup = setup,
+};
diff --git a/testcases/kernel/syscalls/memfd_create/memfd_create_common.h b/testcases/kernel/syscalls/memfd_create/memfd_create_common.h
new file mode 100644
index 0000000..f07cc8c
--- /dev/null
+++ b/testcases/kernel/syscalls/memfd_create/memfd_create_common.h
@@ -0,0 +1,525 @@
+/*
+ * Copyright (C) 2017  Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MEMFD_TEST_COMMON
+#define MEMFD_TEST_COMMON
+
+#include <sys/types.h>
+#include <sys/syscall.h>
+#include <sys/uio.h>
+#include <lapi/fallocate.h>
+#include <lapi/fcntl.h>
+#include <lapi/memfd.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define TST_NO_DEFAULT_MAIN
+#include <tst_test.h>
+
+#include "linux_syscall_numbers.h"
+
+#define MFD_DEF_SIZE 8192
+#define STACK_SIZE 65536
+
+enum assert_retval {
+	ALL_OK,
+	MEMFD_FAIL,
+	MEMFD_MISMATCH,
+	FTRUNCATE_FAIL,
+	FCNTL_FAIL,
+	GET_SEALS_MISMATCH,
+	ADD_SEALS_FAIL,
+	ADD_SEALS_MISMATCH,
+	FSTAT_FAIL,
+	FILE_SIZE_MISMATCH,
+	OPEN_MISMATCH,
+	OPEN_FAIL,
+	MPROTECT_FAIL,
+	FALLOCATE_PUNCH_FAIL,
+	WRITE_FAIL,
+	WRITE_MISMATCH,
+	MUNMAP_FAIL,
+	MMAP_FAIL,
+	MMAP_MISMATCH,
+	MMAP_MPROT_MISMATCH,
+	FALLOCATE_PUNCH_MISMATCH,
+	FTRUNCATE_SHRINK_MISMATCH,
+	FALLOCATE_ALLOC_FAIL,
+	FTRUNCATE_GROW_MISMATCH,
+	FALLOCATE_ALLOC_MISMATCH,
+	PWRITE_FAIL,
+	PWRITE_MISMATCH,
+	READ_FAIL,
+	READ_MISMATCH,
+	CLOSE_FAIL,
+};
+
+const char *err_msg[] = {
+	"all OK",
+	"memfd_create() failed",
+	"memfd_create() succeeded, but failure expected",
+	"ftruncate() failed",
+	"fcntl() failed",
+	"GET_SEALS() returned unexpected value",
+	"ADD_SEALS() failed",
+	"ADD_SEALS() didn't fail as expected",
+	"fstat() failed",
+	"wrong file size",
+	"open() didn't fail as expected",
+	"open() failed",
+	"mprotect() failed",
+	"fallocate(PUNCH_HOLE) failed",
+	"write() failed",
+	"write() didn't fail as expected",
+	"munmap() failed",
+	"mmap() failed",
+	"mmap() didn't fail as expected",
+	"mmap()+mprotect() didn't fail as expected",
+	"fallocate(PUNCH_HOLE) didn't fail as expected",
+	"ftruncate(SHRINK) didn't fail as expected",
+	"fallocate(ALLOC) failed",
+	"ftruncate(GROW) didn't fail as expected",
+	"fallocate(ALLOC) didn't fail as expected",
+	"pwrite() failed",
+	"pwrite() didn't fail as expected",
+	"read() failed",
+	"read() didn't fail as expected",
+	"close() failed",
+};
+
+#define STRINGIFY(A) #A
+
+#define CHECK_RESULT(func2call) ({ \
+	int result; \
+	result = func2call; \
+	if (result < ALL_OK) \
+		tst_brk(TFAIL, "%s: %s", STRINGIFY(func2call), \
+			err_msg[-result]); \
+	else \
+		tst_res(TPASS, "%s", STRINGIFY(func2call)); \
+	result; \
+})
+
+#define ASSERT_HAVE_MEMFD_CREATE() do { \
+	int r; \
+	r = mfd_assert_new("dummy_call", 0, 0); \
+	if (r < 0) \
+		tst_brk(TCONF, "memfd_create does not exist on your system."); \
+		SAFE_CLOSE(r); \
+	} while (0)
+
+static int sys_memfd_create(const char *name,
+		unsigned int flags)
+{
+	return syscall(__NR_memfd_create, name, flags);
+}
+
+static int mfd_assert_new(const char *name, loff_t sz, unsigned int flags)
+{
+	int fd, r;
+
+	fd = sys_memfd_create(name, flags);
+	if (fd < 0)
+		return -MEMFD_FAIL;
+
+	r = ftruncate(fd, sz);
+	if (r < 0)
+		return -FTRUNCATE_FAIL;
+
+	return fd;
+}
+
+static int mfd_fail_new(const char *name, unsigned int flags)
+{
+	int fd;
+
+	fd = sys_memfd_create(name, flags);
+	if (fd >= 0) {
+		close(fd);
+		return -MEMFD_MISMATCH;
+	}
+
+	return fd;
+}
+
+static int mfd_assert_get_seals(int fd)
+{
+	int r;
+
+	r = fcntl(fd, F_GET_SEALS);
+	if (r < 0)
+		return -FCNTL_FAIL;
+
+	return r;
+}
+
+static int mfd_assert_has_seals(int fd, int seals)
+{
+	int s;
+
+	s = mfd_assert_get_seals(fd);
+	if (s < 0)
+		return s;
+
+	if (s != seals)
+		return -GET_SEALS_MISMATCH;
+
+	return ALL_OK;
+}
+
+static int mfd_assert_add_seals(int fd, int seals)
+{
+	int r;
+
+	r = mfd_assert_get_seals(fd);
+	if (r < 0)
+		return r;
+
+	r = fcntl(fd, F_ADD_SEALS, seals);
+	if (r < 0)
+		return -ADD_SEALS_FAIL;
+
+	return ALL_OK;
+}
+
+static int mfd_fail_add_seals(int fd, int seals)
+{
+	int r;
+	int s;
+
+	r = fcntl(fd, F_GET_SEALS);
+	if (r < 0)
+		s = 0;
+	else
+		s = r;
+
+	r = fcntl(fd, F_ADD_SEALS, seals);
+	if (r >= 0)
+		return -ADD_SEALS_MISMATCH;
+
+	return ALL_OK;
+}
+
+static int mfd_assert_size(int fd, size_t size)
+{
+	struct stat st;
+	int r;
+
+	r = fstat(fd, &st);
+	if (r < 0)
+		return -FSTAT_FAIL;
+	else if (st.st_size != (long)size)
+		return -FILE_SIZE_MISMATCH;
+
+	return ALL_OK;
+}
+
+static int mfd_assert_open(int fd, int flags, mode_t mode)
+{
+	char buf[512];
+	int r;
+
+	sprintf(buf, "/proc/self/fd/%d", fd);
+
+	r = open(buf, flags, mode);
+	if (r < 0)
+		return -OPEN_FAIL;
+
+	return r;
+}
+
+static int mfd_fail_open(int fd, int flags, mode_t mode)
+{
+	char buf[512];
+	int r;
+
+	sprintf(buf, "/proc/self/fd/%d", fd);
+
+	r = open(buf, flags, mode);
+	if (r >= 0)
+		return -OPEN_MISMATCH;
+
+	return ALL_OK;
+}
+
+static int mfd_assert_read(int fd)
+{
+	char buf[16];
+	void *p;
+	ssize_t l;
+
+	l = read(fd, buf, sizeof(buf));
+	if (l != sizeof(buf))
+		return -READ_FAIL;
+
+	/* verify PROT_READ *is* allowed */
+	p = mmap(NULL,
+			MFD_DEF_SIZE,
+			PROT_READ,
+			MAP_PRIVATE,
+			fd,
+			0);
+	if (p == MAP_FAILED)
+		return -MMAP_FAIL;
+
+	if (munmap(p, MFD_DEF_SIZE) < 0)
+		return -MUNMAP_FAIL;
+
+	/* verify MAP_PRIVATE is *always* allowed (even writable) */
+	p = mmap(NULL,
+			MFD_DEF_SIZE,
+			PROT_READ | PROT_WRITE,
+			MAP_PRIVATE,
+			fd,
+			0);
+	if (p == MAP_FAILED)
+		return -MMAP_FAIL;
+
+	if (munmap(p, MFD_DEF_SIZE) < 0)
+		return -MUNMAP_FAIL;
+
+	return ALL_OK;
+}
+
+static int mfd_assert_write(int fd)
+{
+	void *p;
+	int r;
+
+	/* verify write() succeeds */
+	if (write(fd, "\0\0\0\0", 4) != 4)
+		return -WRITE_FAIL;
+
+	/* verify PROT_READ | PROT_WRITE is allowed */
+	p = mmap(NULL,
+			MFD_DEF_SIZE,
+			PROT_READ | PROT_WRITE,
+			MAP_SHARED,
+			fd,
+			0);
+	if (p == MAP_FAILED)
+		return -MMAP_FAIL;
+
+	*(char *)p = 0;
+	if (munmap(p, MFD_DEF_SIZE) < 0)
+		return -MUNMAP_FAIL;
+
+	/* verify PROT_WRITE is allowed */
+	p = mmap(NULL,
+			MFD_DEF_SIZE,
+			PROT_WRITE,
+			MAP_SHARED,
+			fd,
+			0);
+	if (p == MAP_FAILED)
+		return -MMAP_FAIL;
+
+	*(char *)p = 0;
+	if (munmap(p, MFD_DEF_SIZE) < 0)
+		return -MUNMAP_FAIL;
+
+	/* verify PROT_READ with MAP_SHARED is allowed and a following
+	 * mprotect(PROT_WRITE) allows writing
+	 */
+	p = mmap(NULL,
+			MFD_DEF_SIZE,
+			PROT_READ,
+			MAP_SHARED,
+			fd,
+			0);
+	if (p == MAP_FAILED)
+		return -MMAP_FAIL;
+
+	r = mprotect(p, MFD_DEF_SIZE, PROT_READ | PROT_WRITE);
+	if (r < 0)
+		return -MPROTECT_FAIL;
+
+	*(char *)p = 0;
+	if (munmap(p, MFD_DEF_SIZE) < 0)
+		return -MUNMAP_FAIL;
+
+	/* verify PUNCH_HOLE works */
+	r = fallocate(fd,
+			FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
+			0,
+			MFD_DEF_SIZE);
+	if (r < 0)
+		return -FALLOCATE_PUNCH_FAIL;
+
+	return ALL_OK;
+}
+
+static int mfd_fail_write(int fd)
+{
+	ssize_t l;
+	void *p;
+	int r;
+
+	/* verify write() fails */
+	l = write(fd, "data", 4);
+	if (l != -EPERM)
+		return -WRITE_MISMATCH;
+
+	/* verify PROT_READ | PROT_WRITE is not allowed */
+	p = mmap(NULL,
+			MFD_DEF_SIZE,
+			PROT_READ | PROT_WRITE,
+			MAP_SHARED,
+			fd,
+			0);
+	if (p != MAP_FAILED)
+		return -MMAP_MISMATCH;
+
+	/* verify PROT_WRITE is not allowed */
+	p = mmap(NULL,
+			MFD_DEF_SIZE,
+			PROT_WRITE,
+			MAP_SHARED,
+			fd,
+			0);
+	if (p != MAP_FAILED)
+		return -MMAP_MISMATCH;
+
+	/* Verify PROT_READ with MAP_SHARED with a following mprotect is not
+	 * allowed. Note that for r/w the kernel already prevents the mmap.
+	 */
+	p = mmap(NULL,
+			MFD_DEF_SIZE,
+			PROT_READ,
+			MAP_SHARED,
+			fd,
+			0);
+	if (p != MAP_FAILED) {
+		r = mprotect(p, MFD_DEF_SIZE, PROT_READ | PROT_WRITE);
+		if (r >= 0)
+			return -MMAP_MPROT_MISMATCH;
+	}
+
+	/* verify PUNCH_HOLE fails */
+	r = fallocate(fd,
+			FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
+			0,
+			MFD_DEF_SIZE);
+	if (r >= 0)
+		return -FALLOCATE_PUNCH_MISMATCH;
+
+	return ALL_OK;
+}
+
+static int mfd_assert_shrink(int fd)
+{
+	int fd2, r;
+
+	r = ftruncate(fd, MFD_DEF_SIZE / 2);
+	if (r < 0)
+		return -FTRUNCATE_FAIL;
+
+	r = mfd_assert_size(fd, MFD_DEF_SIZE / 2);
+	if (r < 0)
+		return r;
+
+	fd2 = mfd_assert_open(fd,
+			O_RDWR | O_CREAT | O_TRUNC,
+			0600);
+	if (fd2 < 0)
+		return fd2;
+
+	if (close(fd2) < 0)
+		return -CLOSE_FAIL;
+
+	return mfd_assert_size(fd, 0);
+}
+
+static int mfd_fail_shrink(int fd)
+{
+	int r;
+
+	r = ftruncate(fd, MFD_DEF_SIZE / 2);
+	if (r >= 0)
+		return -FTRUNCATE_SHRINK_MISMATCH;
+
+	return mfd_fail_open(fd,
+			O_RDWR | O_CREAT | O_TRUNC,
+			0600);
+}
+
+static int mfd_assert_grow(int fd)
+{
+	int r;
+
+	r = ftruncate(fd, MFD_DEF_SIZE * 2);
+	if (r < 0)
+		return -FTRUNCATE_FAIL;
+
+	r = mfd_assert_size(fd, MFD_DEF_SIZE * 2);
+	if (r < 0)
+		return r;
+
+	r = fallocate(fd,
+			0,
+			0,
+			MFD_DEF_SIZE * 4);
+	if (r < 0)
+		return -FALLOCATE_ALLOC_FAIL;
+
+	return mfd_assert_size(fd, MFD_DEF_SIZE * 4);
+}
+
+static int mfd_fail_grow(int fd)
+{
+	int r;
+
+	r = ftruncate(fd, MFD_DEF_SIZE * 2);
+	if (r >= 0)
+		return -FTRUNCATE_GROW_MISMATCH;
+
+	r = fallocate(fd,
+			0,
+			0,
+			MFD_DEF_SIZE * 4);
+	if (r >= 0)
+		return -FALLOCATE_ALLOC_MISMATCH;
+
+	return ALL_OK;
+}
+
+static int mfd_assert_grow_write(int fd)
+{
+	static char buf[MFD_DEF_SIZE * 8];
+	ssize_t l;
+
+	l = pwrite(fd, buf, sizeof(buf), 0);
+	if (l != sizeof(buf))
+		return -PWRITE_FAIL;
+
+	return mfd_assert_size(fd, MFD_DEF_SIZE * 8);
+}
+
+static int mfd_fail_grow_write(int fd)
+{
+	static char buf[MFD_DEF_SIZE * 8];
+	ssize_t l;
+
+	l = pwrite(fd, buf, sizeof(buf), 0);
+	if (l == sizeof(buf))
+		return -PWRITE_MISMATCH;
+
+	return ALL_OK;
+}
+
+#endif
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [LTP] [PATCH v2 6/6] syscalls/memfd_create02.c: added new test
  2017-03-06 17:45 [LTP] [PATCH v2 0/6] Added memfd_create() testsuite Jakub Racek
                   ` (4 preceding siblings ...)
  2017-03-06 17:45 ` [LTP] [PATCH v2 5/6] syscalls: added memfd_create dir and memfd_create/memfd_create01.c Jakub Racek
@ 2017-03-06 17:45 ` Jakub Racek
  2017-03-07 12:21   ` Cyril Hrubis
  5 siblings, 1 reply; 12+ messages in thread
From: Jakub Racek @ 2017-03-06 17:45 UTC (permalink / raw)
  To: ltp

Signed-off-by: Jakub Racek <jracek@redhat.com>
---
 runtest/syscalls                                   |  1 +
 testcases/kernel/syscalls/.gitignore               |  1 +
 .../kernel/syscalls/memfd_create/memfd_create02.c  | 92 ++++++++++++++++++++++
 3 files changed, 94 insertions(+)
 create mode 100644 testcases/kernel/syscalls/memfd_create/memfd_create02.c

diff --git a/runtest/syscalls b/runtest/syscalls
index fd305ce..3d59686 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1450,3 +1450,4 @@ futex_wait_bitset01 futex_wait_bitset01
 futex_wait_bitset02 futex_wait_bitset02
 
 memfd_create01 memfd_create01
+memfd_create02 memfd_create02
diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore
index 915b1b9..75227f9 100644
--- a/testcases/kernel/syscalls/.gitignore
+++ b/testcases/kernel/syscalls/.gitignore
@@ -1117,3 +1117,4 @@
 /perf_event_open/perf_event_open01
 /perf_event_open/perf_event_open02
 /memfd_create/memfd_create01
+/memfd_create/memfd_create02
diff --git a/testcases/kernel/syscalls/memfd_create/memfd_create02.c b/testcases/kernel/syscalls/memfd_create/memfd_create02.c
new file mode 100644
index 0000000..b7c2815
--- /dev/null
+++ b/testcases/kernel/syscalls/memfd_create/memfd_create02.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2017  Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+ /*
+  *  Based on Linux/tools/testing/selftests/memfd/memfd_test.c
+  *  by David Herrmann <dh.herrmann@gmail.com>
+  *
+  *  24/02/2017   Port to LTP    <jracek@redhat.com>
+  */
+
+#define _GNU_SOURCE
+
+#include <tst_test.h>
+
+#include "memfd_create_common.h"
+
+static char buf[2048];
+static char term_buf[2048];
+
+static const struct tcase {
+	char *descr;
+	char *memfd_name;
+	int flags;
+	int memfd_create_exp_err;
+} tcases[] = {
+	/*
+	 * Test memfd_create() syscall
+	 * Verify syscall-argument validation, including name checks,
+	 * flag validation and more.
+	 */
+	{"invalid name fail 1",   NULL,     0,                      EFAULT },
+	{"invalid name fail 2",   buf,      0,                      EINVAL },
+	{"invalid name fail 3",   term_buf, 0,                      EINVAL },
+
+	{"invalid flags fail 1", "test",  -500,                     EINVAL },
+	{"invalid flags fail 2", "test",  0x0100,                   EINVAL },
+	{"invalid flags fail 3", "test",  ~MFD_CLOEXEC,             EINVAL },
+	{"invalid flags fail 4", "test",  ~MFD_ALLOW_SEALING,       EINVAL },
+	{"invalid flags fail 5", "test",  ~0,                       EINVAL },
+	{"invalid flags fail 6", "test",  0x80000000U,              EINVAL },
+
+	{"valid flags 1 pass", "test",  MFD_CLOEXEC,                     0 },
+	{"valid flags 2 pass", "test",  MFD_ALLOW_SEALING,               0 },
+	{"valid flags 3 pass", "test",  MFD_CLOEXEC | MFD_ALLOW_SEALING, 0 },
+	{"valid flags 4 pass", "test",  0,                               0 },
+	{"valid flags 5 pass", "",      0,                               0 },
+};
+
+static void setup(void)
+{
+	ASSERT_HAVE_MEMFD_CREATE();
+
+	memset(buf, 0xff, sizeof(buf));
+
+	memset(term_buf, 0xff, sizeof(term_buf));
+	term_buf[sizeof(term_buf) - 1] = 0;
+}
+
+static void verify_memfd_create_errno(unsigned int n)
+{
+	const struct tcase *tc;
+
+	tc = &tcases[n];
+
+	TEST(mfd_fail_new(tc->memfd_name, tc->flags));
+	if (TEST_ERRNO != tc->memfd_create_exp_err)
+		tst_brk(TFAIL, "test '%s'", tc->descr);
+	else
+		tst_res(TPASS, "test '%s'", tc->descr);
+
+	if (TEST_RETURN > 0)
+		SAFE_CLOSE(TEST_RETURN);
+}
+
+static struct tst_test test = {
+	.tid = "memfd_create02",
+	.test = verify_memfd_create_errno,
+	.tcnt = ARRAY_SIZE(tcases),
+	.setup = setup,
+};
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [LTP] [PATCH v2 4/6] Added fallocate() flags and wrapper to lapi
  2017-03-06 17:45 ` [LTP] [PATCH v2 4/6] Added fallocate() flags and wrapper to lapi Jakub Racek
@ 2017-03-07 11:44   ` Cyril Hrubis
  0 siblings, 0 replies; 12+ messages in thread
From: Cyril Hrubis @ 2017-03-07 11:44 UTC (permalink / raw)
  To: ltp

Hi!
This patch should also remove the original file
(testcases/kernel/syscalls/fallocate/fallocate.h) and fix the fallocate
testcases to include the header in lapi/.

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [LTP] [PATCH v2 5/6] syscalls: added memfd_create dir and memfd_create/memfd_create01.c
  2017-03-06 17:45 ` [LTP] [PATCH v2 5/6] syscalls: added memfd_create dir and memfd_create/memfd_create01.c Jakub Racek
@ 2017-03-07 12:17   ` Cyril Hrubis
  2017-03-07 13:08     ` Jakub =?unknown-8bit?q?Ra=C4=8Dek?=
  0 siblings, 1 reply; 12+ messages in thread
From: Cyril Hrubis @ 2017-03-07 12:17 UTC (permalink / raw)
  To: ltp

Hi!
> +/*
> + * Do few basic sealing tests to see whether setting/retrieving seals works.
> + */
> +static void test_basic(int fd)
> +{
> +	/* add basic seals */
> +	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_SHRINK |
> +			F_SEAL_WRITE));
> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SHRINK |
> +			F_SEAL_WRITE));
> +
> +	/* add them again */
> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_SHRINK |
> +			F_SEAL_WRITE));
> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SHRINK |
> +			F_SEAL_WRITE));
> +
> +	/* add more seals and seal against sealing */
> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_GROW | F_SEAL_SEAL));
> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SHRINK |
> +			F_SEAL_GROW |
> +			F_SEAL_WRITE |
> +			F_SEAL_SEAL));
> +
> +	/* verify that sealing no longer works */
> +	CHECK_RESULT(mfd_fail_add_seals(fd, F_SEAL_GROW));
> +	CHECK_RESULT(mfd_fail_add_seals(fd, 0));
> +
> +	tst_res(TPASS, "%s", __func__);
> +}
> +
> +/*
> + * Verify that no sealing is possible when memfd is created without
> + * MFD_ALLOW_SEALING flag.
> + */
> +static void test_no_sealing_without_flag(int fd)
> +{
> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SEAL));
> +	CHECK_RESULT(mfd_fail_add_seals(fd, F_SEAL_SHRINK |
> +			F_SEAL_GROW |
> +			F_SEAL_WRITE));
> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SEAL));
> +
> +	tst_res(TPASS, "%s", __func__);
> +}
> +
> +/*
> + * Test SEAL_WRITE
> + * Test whether SEAL_WRITE actually prevents modifications.
> + */
> +static void test_seal_write(int fd)
> +{
> +	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_WRITE));
> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_WRITE));
> +
> +	CHECK_RESULT(mfd_assert_read(fd));
> +	CHECK_RESULT(mfd_fail_write(fd));
> +	CHECK_RESULT(mfd_assert_shrink(fd));
> +	CHECK_RESULT(mfd_assert_grow(fd));
> +	CHECK_RESULT(mfd_fail_grow_write(fd));
> +
> +	tst_res(TPASS, "%s", __func__);
> +}
> +
> +/*
> + * Test SEAL_SHRINK
> + * Test whether SEAL_SHRINK actually prevents shrinking
> + */
> +static void test_seal_shrink(int fd)
> +{
> +	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_SHRINK));
> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SHRINK));
> +
> +	CHECK_RESULT(mfd_assert_read(fd));
> +	CHECK_RESULT(mfd_assert_write(fd));
> +	CHECK_RESULT(mfd_fail_shrink(fd));
> +	CHECK_RESULT(mfd_assert_grow(fd));
> +	CHECK_RESULT(mfd_assert_grow_write(fd));
> +
> +	tst_res(TPASS, "%s", __func__);
> +}
> +
> +/*
> + * Test SEAL_GROW
> + * Test whether SEAL_GROW actually prevents growing
> + */
> +static void test_seal_grow(int fd)
> +{
> +	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_GROW));
> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_GROW));
> +
> +	CHECK_RESULT(mfd_assert_read(fd));
> +	CHECK_RESULT(mfd_assert_write(fd));
> +	CHECK_RESULT(mfd_assert_shrink(fd));
> +	CHECK_RESULT(mfd_fail_grow(fd));
> +	CHECK_RESULT(mfd_fail_grow_write(fd));
> +
> +	tst_res(TPASS, "%s", __func__);
> +}
> +
> +/*
> + * Test SEAL_SHRINK | SEAL_GROW
> + * Test whether SEAL_SHRINK | SEAL_GROW actually prevents resizing
> + */
> +static void test_seal_resize(int fd)
> +{
> +	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW));
> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW));
> +
> +	CHECK_RESULT(mfd_assert_read(fd));
> +	CHECK_RESULT(mfd_assert_write(fd));
> +	CHECK_RESULT(mfd_fail_shrink(fd));
> +	CHECK_RESULT(mfd_fail_grow(fd));
> +	CHECK_RESULT(mfd_fail_grow_write(fd));
> +
> +	tst_res(TPASS, "%s", __func__);
> +}
> +
> +/*
> + * Test sharing via dup()
> + * Test that seals are shared between dupped FDs and they're all equal.
> + */
> +static void test_share_dup(int fd)
> +{
> +	int fd2;
> +
> +	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
> +
> +	fd2 = SAFE_DUP(fd);
> +	CHECK_RESULT(mfd_assert_has_seals(fd2, 0));
> +
> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_WRITE));
> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_WRITE));
> +	CHECK_RESULT(mfd_assert_has_seals(fd2, F_SEAL_WRITE));
> +
> +	CHECK_RESULT(mfd_assert_add_seals(fd2, F_SEAL_SHRINK));
> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK));
> +	CHECK_RESULT(mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK));
> +
> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_SEAL));
> +	CHECK_RESULT(mfd_assert_has_seals(fd,
> +		F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL));
> +	CHECK_RESULT(mfd_assert_has_seals(fd2,
> +		F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL));
> +
> +	CHECK_RESULT(mfd_fail_add_seals(fd, F_SEAL_GROW));
> +	CHECK_RESULT(mfd_fail_add_seals(fd2, F_SEAL_GROW));
> +	CHECK_RESULT(mfd_fail_add_seals(fd, F_SEAL_SEAL));
> +	CHECK_RESULT(mfd_fail_add_seals(fd2, F_SEAL_SEAL));
> +
> +	SAFE_CLOSE(fd2);
> +
> +	CHECK_RESULT(mfd_fail_add_seals(fd, F_SEAL_GROW));
> +
> +	tst_res(TPASS, "%s", __func__);
> +}
> +
> +/*
> + * Test sealing with active mmap()s
> + * Modifying seals is only allowed if no other mmap() refs exist.
> + */
> +static void test_share_mmap(int fd)
> +{
> +	void *p;
> +
> +	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
> +
> +	/* shared/writable ref prevents sealing WRITE, but allows others */
> +	p = SAFE_MMAP(NULL,
> +			MFD_DEF_SIZE,
> +			PROT_READ | PROT_WRITE,
> +			MAP_SHARED,
> +			fd,
> +			0);
> +	CHECK_RESULT(mfd_fail_add_seals(fd, F_SEAL_WRITE));
> +	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_SHRINK));
> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SHRINK));
> +	SAFE_MUNMAP(p, MFD_DEF_SIZE);
> +
> +	/* readable ref allows sealing */
> +	p = SAFE_MMAP(NULL,
> +			MFD_DEF_SIZE,
> +			PROT_READ,
> +			MAP_PRIVATE,
> +			fd,
> +			0);
> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_WRITE));
> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK));
> +	SAFE_MUNMAP(p, MFD_DEF_SIZE);
> +
> +	tst_res(TPASS, "%s", __func__);
> +}
> +
> +/*
> + * Test sealing with open(/proc/self/fd/%d)
> + * Via /proc we can get access to a separate file-context for the same memfd.
> + * This is *not* like dup(), but like a real separate open(). Make sure the
> + * semantics are as expected and we correctly check for RDONLY / WRONLY / RDWR.
> + */
> +static void test_share_open(int fd)
> +{
> +	int fd2;
> +
> +	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
> +
> +	fd2 = CHECK_RESULT(mfd_assert_open(fd, O_RDWR, 0));
> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_WRITE));
> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_WRITE));
> +	CHECK_RESULT(mfd_assert_has_seals(fd2, F_SEAL_WRITE));
> +
> +	CHECK_RESULT(mfd_assert_add_seals(fd2, F_SEAL_SHRINK));
> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK));
> +	CHECK_RESULT(mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK));
> +
> +	SAFE_CLOSE(fd);
> +	fd = CHECK_RESULT(mfd_assert_open(fd2, O_RDONLY, 0));
> +
> +	CHECK_RESULT(mfd_fail_add_seals(fd, F_SEAL_SEAL));
> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK));
> +	CHECK_RESULT(mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK));
> +
> +	SAFE_CLOSE(fd2);
> +
> +	tst_res(TPASS, "%s", __func__);
> +}
> +
> +static const struct tcase {
> +	int flags;
> +	void (*func)(int fd);
> +} tcases[] = {
> +	{MFD_ALLOW_SEALING, &test_basic},
> +	{0,                 &test_no_sealing_without_flag},
> +
> +	{MFD_ALLOW_SEALING, &test_seal_write},
> +	{MFD_ALLOW_SEALING, &test_seal_shrink},
> +	{MFD_ALLOW_SEALING, &test_seal_grow},
> +	{MFD_ALLOW_SEALING, &test_seal_resize},
> +
> +	{MFD_ALLOW_SEALING, &test_share_dup},
> +	{MFD_ALLOW_SEALING, &test_share_mmap},
> +	{MFD_ALLOW_SEALING, &test_share_open},
> +};
> +
> +static void verify_memfd_create(unsigned int n)
> +{
> +	const struct tcase *tc;
> +
> +	tc = &tcases[n];
> +
> +	TEST(mfd_assert_new(TCID, MFD_DEF_SIZE, tc->flags));
> +	if (TEST_RETURN < 0)
> +		tst_brk(TBROK | TERRNO, "memfd_create() failed unexpectedly");
> +
> +	tc->func(TEST_RETURN);
> +
> +	if (TEST_RETURN > 0)
> +		SAFE_CLOSE(TEST_RETURN);
> +}
> +
> +static void setup(void)
> +{
> +	ASSERT_HAVE_MEMFD_CREATE();
> +}
> +
> +static struct tst_test test = {
> +	.tid = "memfd_create01",
> +	.test = verify_memfd_create,
> +	.tcnt = ARRAY_SIZE(tcases),
> +	.setup = setup,
> +};
> diff --git a/testcases/kernel/syscalls/memfd_create/memfd_create_common.h b/testcases/kernel/syscalls/memfd_create/memfd_create_common.h
> new file mode 100644
> index 0000000..f07cc8c
> --- /dev/null
> +++ b/testcases/kernel/syscalls/memfd_create/memfd_create_common.h
> @@ -0,0 +1,525 @@
> +/*
> + * Copyright (C) 2017  Red Hat, Inc.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it would be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#ifndef MEMFD_TEST_COMMON
> +#define MEMFD_TEST_COMMON
> +
> +#include <sys/types.h>
> +#include <sys/syscall.h>
> +#include <sys/uio.h>
> +#include <lapi/fallocate.h>
> +#include <lapi/fcntl.h>
> +#include <lapi/memfd.h>
> +#include <errno.h>
> +#include <string.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <unistd.h>
> +
> +#define TST_NO_DEFAULT_MAIN
> +#include <tst_test.h>
> +
> +#include "linux_syscall_numbers.h"
> +
> +#define MFD_DEF_SIZE 8192
> +#define STACK_SIZE 65536
> +
> +enum assert_retval {
> +	ALL_OK,
> +	MEMFD_FAIL,
> +	MEMFD_MISMATCH,
> +	FTRUNCATE_FAIL,
> +	FCNTL_FAIL,
> +	GET_SEALS_MISMATCH,
> +	ADD_SEALS_FAIL,
> +	ADD_SEALS_MISMATCH,
> +	FSTAT_FAIL,
> +	FILE_SIZE_MISMATCH,
> +	OPEN_MISMATCH,
> +	OPEN_FAIL,
> +	MPROTECT_FAIL,
> +	FALLOCATE_PUNCH_FAIL,
> +	WRITE_FAIL,
> +	WRITE_MISMATCH,
> +	MUNMAP_FAIL,
> +	MMAP_FAIL,
> +	MMAP_MISMATCH,
> +	MMAP_MPROT_MISMATCH,
> +	FALLOCATE_PUNCH_MISMATCH,
> +	FTRUNCATE_SHRINK_MISMATCH,
> +	FALLOCATE_ALLOC_FAIL,
> +	FTRUNCATE_GROW_MISMATCH,
> +	FALLOCATE_ALLOC_MISMATCH,
> +	PWRITE_FAIL,
> +	PWRITE_MISMATCH,
> +	READ_FAIL,
> +	READ_MISMATCH,
> +	CLOSE_FAIL,
> +};
> +
> +const char *err_msg[] = {
> +	"all OK",
> +	"memfd_create() failed",
> +	"memfd_create() succeeded, but failure expected",
> +	"ftruncate() failed",
> +	"fcntl() failed",
> +	"GET_SEALS() returned unexpected value",
> +	"ADD_SEALS() failed",
> +	"ADD_SEALS() didn't fail as expected",
> +	"fstat() failed",
> +	"wrong file size",
> +	"open() didn't fail as expected",
> +	"open() failed",
> +	"mprotect() failed",
> +	"fallocate(PUNCH_HOLE) failed",
> +	"write() failed",
> +	"write() didn't fail as expected",
> +	"munmap() failed",
> +	"mmap() failed",
> +	"mmap() didn't fail as expected",
> +	"mmap()+mprotect() didn't fail as expected",
> +	"fallocate(PUNCH_HOLE) didn't fail as expected",
> +	"ftruncate(SHRINK) didn't fail as expected",
> +	"fallocate(ALLOC) failed",
> +	"ftruncate(GROW) didn't fail as expected",
> +	"fallocate(ALLOC) didn't fail as expected",
> +	"pwrite() failed",
> +	"pwrite() didn't fail as expected",
> +	"read() failed",
> +	"read() didn't fail as expected",
> +	"close() failed",
> +};
> +
> +#define STRINGIFY(A) #A
> +
> +#define CHECK_RESULT(func2call) ({ \
> +	int result; \
> +	result = func2call; \
> +	if (result < ALL_OK) \
> +		tst_brk(TFAIL, "%s: %s", STRINGIFY(func2call), \
> +			err_msg[-result]); \
> +	else \
> +		tst_res(TPASS, "%s", STRINGIFY(func2call)); \
> +	result; \
> +})
> +
> +#define ASSERT_HAVE_MEMFD_CREATE() do { \
> +	int r; \
> +	r = mfd_assert_new("dummy_call", 0, 0); \
> +	if (r < 0) \
> +		tst_brk(TCONF, "memfd_create does not exist on your system."); \
> +		SAFE_CLOSE(r); \
                ^
		The indentation here is confusing.

> +	} while (0)
> +
> +static int sys_memfd_create(const char *name,
> +		unsigned int flags)
> +{
> +	return syscall(__NR_memfd_create, name, flags);
> +}
> +
> +static int mfd_assert_new(const char *name, loff_t sz, unsigned int flags)
> +{
> +	int fd, r;
> +
> +	fd = sys_memfd_create(name, flags);
> +	if (fd < 0)
> +		return -MEMFD_FAIL;
> +
> +	r = ftruncate(fd, sz);
> +	if (r < 0)
> +		return -FTRUNCATE_FAIL;
> +
> +	return fd;
> +}

This indirection (returning error number and matching it agains table is
confusing as well).

I wonder if we should do this similarily to safe macros, i.e. doing
something as:

#define SAFE_MFD_NEW(name, sz, flags) \
        safe_mfd_new(__FILE__, __LINE__, name, flags);

static int safe_mfd_new(const char *filename, const char lineno,
                        const char *name, unsigned int flags)
{
	int fd;

	if (sys_memfd_create(name, flags)) {
		tst_brk(TBROK | TERRNO,
		        "%s:%i: memfd_create(%s,%u) failed",
			file, lineno, name, flags);
	}

	return fd;
}

Then we could do something as:

	int fd;

	fd = SAFE_MFD_NEW("foo", 0);
	SAFE_FTRUNCATE(fd, sz);

In the main test function, which seems to be much clearer code to me.

> +static int mfd_fail_new(const char *name, unsigned int flags)
> +{
> +	int fd;
> +
> +	fd = sys_memfd_create(name, flags);
> +	if (fd >= 0) {
> +		close(fd);
> +		return -MEMFD_MISMATCH;
> +	}
> +
> +	return fd;
> +}
> +
> +static int mfd_assert_get_seals(int fd)
> +{
> +	int r;
> +
> +	r = fcntl(fd, F_GET_SEALS);
> +	if (r < 0)
> +		return -FCNTL_FAIL;
> +
> +	return r;
> +}

This could be just replaced with SAFE_FCNTL() in the test code.

> +static int mfd_assert_has_seals(int fd, int seals)
> +{
> +	int s;
> +
> +	s = mfd_assert_get_seals(fd);
> +	if (s < 0)
> +		return s;
> +
> +	if (s != seals)
> +		return -GET_SEALS_MISMATCH;
> +
> +	return ALL_OK;
> +}

This as well, you can even just do:

	int s;

	s = SAFE_FCNTL(fd, F_GET_SEALS);

	if (seals != s) {
		tst_res(TFAIL, "Unexpected seals %i, expected %i",
		         seals, s);
	}

> +static int mfd_assert_add_seals(int fd, int seals)
> +{
> +	int r;
> +
> +	r = mfd_assert_get_seals(fd);
> +	if (r < 0)
> +		return r;
> +
> +	r = fcntl(fd, F_ADD_SEALS, seals);
> +	if (r < 0)
> +		return -ADD_SEALS_FAIL;
> +
> +	return ALL_OK;
> +}

Again this is just one SAFE_FCNTL();

> +static int mfd_fail_add_seals(int fd, int seals)
> +{
> +	int r;
> +	int s;
> +
> +	r = fcntl(fd, F_GET_SEALS);
> +	if (r < 0)
> +		s = 0;
> +	else
> +		s = r;

This does not make any sense, is the s variable used for anything at
all?

> +	r = fcntl(fd, F_ADD_SEALS, seals);
> +	if (r >= 0)
> +		return -ADD_SEALS_MISMATCH;
> +
> +	return ALL_OK;
> +}

And we can so something as:

#define FAIL_ADD_SEALS(fd, seals) \
        fail_add_seals(__FILE__, __LINE__, fd, seals)

static void fail_add_seals(const char *file, const int lineno,
                           int fd, int seals)
{
	if (fcntl(fd, F_ADD_SEALS, seals) >= 0) {
		tst_res(TFAIL,
		        "%s:%i: fcntl(%i, F_ADD_SEALS, %i) passed unexpectedly",
			file, lineno, fd, seals);
	} else {
		tst_res(TPASS, "%s:%i: fcntl(%i, F_ADD_SEALS, %i) failed",
		        file, lineno, fd, seals);
	}
}

For the negative testcases.

> +static int mfd_assert_size(int fd, size_t size)
> +{
> +	struct stat st;
> +	int r;
> +
> +	r = fstat(fd, &st);
> +	if (r < 0)
> +		return -FSTAT_FAIL;
> +	else if (st.st_size != (long)size)
> +		return -FILE_SIZE_MISMATCH;
> +
> +	return ALL_OK;
> +}

We have SAFE_FSTAT() as well. etc.

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [LTP] [PATCH v2 6/6] syscalls/memfd_create02.c: added new test
  2017-03-06 17:45 ` [LTP] [PATCH v2 6/6] syscalls/memfd_create02.c: added new test Jakub Racek
@ 2017-03-07 12:21   ` Cyril Hrubis
  0 siblings, 0 replies; 12+ messages in thread
From: Cyril Hrubis @ 2017-03-07 12:21 UTC (permalink / raw)
  To: ltp

Hi!
This one looks good, as well as the rest of the patches I didn't comment
on.

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [LTP] [PATCH v2 5/6] syscalls: added memfd_create dir and memfd_create/memfd_create01.c
  2017-03-07 12:17   ` Cyril Hrubis
@ 2017-03-07 13:08     ` Jakub =?unknown-8bit?q?Ra=C4=8Dek?=
  2017-03-07 13:21       ` Cyril Hrubis
  0 siblings, 1 reply; 12+ messages in thread
From: Jakub =?unknown-8bit?q?Ra=C4=8Dek?= @ 2017-03-07 13:08 UTC (permalink / raw)
  To: ltp

Hi,

SAFE_MFD_NEW and others should go to "include/tst_safe_macros.h", right?

If I undestand this correctly, negative testcases will have to stay in
memfd_create_common.h. That means I can't use
SAFE_ macros in those functions/macros, as that would obscure line
numbers. And putting those elsewhere would duplicate a lot of code.

Jakub Racek

On 03/07/2017 01:17 PM, Cyril Hrubis wrote:
> Hi!
>> +/*
>> + * Do few basic sealing tests to see whether setting/retrieving seals works.
>> + */
>> +static void test_basic(int fd)
>> +{
>> +	/* add basic seals */
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
>> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_SHRINK |
>> +			F_SEAL_WRITE));
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SHRINK |
>> +			F_SEAL_WRITE));
>> +
>> +	/* add them again */
>> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_SHRINK |
>> +			F_SEAL_WRITE));
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SHRINK |
>> +			F_SEAL_WRITE));
>> +
>> +	/* add more seals and seal against sealing */
>> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_GROW | F_SEAL_SEAL));
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SHRINK |
>> +			F_SEAL_GROW |
>> +			F_SEAL_WRITE |
>> +			F_SEAL_SEAL));
>> +
>> +	/* verify that sealing no longer works */
>> +	CHECK_RESULT(mfd_fail_add_seals(fd, F_SEAL_GROW));
>> +	CHECK_RESULT(mfd_fail_add_seals(fd, 0));
>> +
>> +	tst_res(TPASS, "%s", __func__);
>> +}
>> +
>> +/*
>> + * Verify that no sealing is possible when memfd is created without
>> + * MFD_ALLOW_SEALING flag.
>> + */
>> +static void test_no_sealing_without_flag(int fd)
>> +{
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SEAL));
>> +	CHECK_RESULT(mfd_fail_add_seals(fd, F_SEAL_SHRINK |
>> +			F_SEAL_GROW |
>> +			F_SEAL_WRITE));
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SEAL));
>> +
>> +	tst_res(TPASS, "%s", __func__);
>> +}
>> +
>> +/*
>> + * Test SEAL_WRITE
>> + * Test whether SEAL_WRITE actually prevents modifications.
>> + */
>> +static void test_seal_write(int fd)
>> +{
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
>> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_WRITE));
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_WRITE));
>> +
>> +	CHECK_RESULT(mfd_assert_read(fd));
>> +	CHECK_RESULT(mfd_fail_write(fd));
>> +	CHECK_RESULT(mfd_assert_shrink(fd));
>> +	CHECK_RESULT(mfd_assert_grow(fd));
>> +	CHECK_RESULT(mfd_fail_grow_write(fd));
>> +
>> +	tst_res(TPASS, "%s", __func__);
>> +}
>> +
>> +/*
>> + * Test SEAL_SHRINK
>> + * Test whether SEAL_SHRINK actually prevents shrinking
>> + */
>> +static void test_seal_shrink(int fd)
>> +{
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
>> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_SHRINK));
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SHRINK));
>> +
>> +	CHECK_RESULT(mfd_assert_read(fd));
>> +	CHECK_RESULT(mfd_assert_write(fd));
>> +	CHECK_RESULT(mfd_fail_shrink(fd));
>> +	CHECK_RESULT(mfd_assert_grow(fd));
>> +	CHECK_RESULT(mfd_assert_grow_write(fd));
>> +
>> +	tst_res(TPASS, "%s", __func__);
>> +}
>> +
>> +/*
>> + * Test SEAL_GROW
>> + * Test whether SEAL_GROW actually prevents growing
>> + */
>> +static void test_seal_grow(int fd)
>> +{
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
>> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_GROW));
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_GROW));
>> +
>> +	CHECK_RESULT(mfd_assert_read(fd));
>> +	CHECK_RESULT(mfd_assert_write(fd));
>> +	CHECK_RESULT(mfd_assert_shrink(fd));
>> +	CHECK_RESULT(mfd_fail_grow(fd));
>> +	CHECK_RESULT(mfd_fail_grow_write(fd));
>> +
>> +	tst_res(TPASS, "%s", __func__);
>> +}
>> +
>> +/*
>> + * Test SEAL_SHRINK | SEAL_GROW
>> + * Test whether SEAL_SHRINK | SEAL_GROW actually prevents resizing
>> + */
>> +static void test_seal_resize(int fd)
>> +{
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
>> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW));
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW));
>> +
>> +	CHECK_RESULT(mfd_assert_read(fd));
>> +	CHECK_RESULT(mfd_assert_write(fd));
>> +	CHECK_RESULT(mfd_fail_shrink(fd));
>> +	CHECK_RESULT(mfd_fail_grow(fd));
>> +	CHECK_RESULT(mfd_fail_grow_write(fd));
>> +
>> +	tst_res(TPASS, "%s", __func__);
>> +}
>> +
>> +/*
>> + * Test sharing via dup()
>> + * Test that seals are shared between dupped FDs and they're all equal.
>> + */
>> +static void test_share_dup(int fd)
>> +{
>> +	int fd2;
>> +
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
>> +
>> +	fd2 = SAFE_DUP(fd);
>> +	CHECK_RESULT(mfd_assert_has_seals(fd2, 0));
>> +
>> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_WRITE));
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_WRITE));
>> +	CHECK_RESULT(mfd_assert_has_seals(fd2, F_SEAL_WRITE));
>> +
>> +	CHECK_RESULT(mfd_assert_add_seals(fd2, F_SEAL_SHRINK));
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK));
>> +	CHECK_RESULT(mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK));
>> +
>> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_SEAL));
>> +	CHECK_RESULT(mfd_assert_has_seals(fd,
>> +		F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL));
>> +	CHECK_RESULT(mfd_assert_has_seals(fd2,
>> +		F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL));
>> +
>> +	CHECK_RESULT(mfd_fail_add_seals(fd, F_SEAL_GROW));
>> +	CHECK_RESULT(mfd_fail_add_seals(fd2, F_SEAL_GROW));
>> +	CHECK_RESULT(mfd_fail_add_seals(fd, F_SEAL_SEAL));
>> +	CHECK_RESULT(mfd_fail_add_seals(fd2, F_SEAL_SEAL));
>> +
>> +	SAFE_CLOSE(fd2);
>> +
>> +	CHECK_RESULT(mfd_fail_add_seals(fd, F_SEAL_GROW));
>> +
>> +	tst_res(TPASS, "%s", __func__);
>> +}
>> +
>> +/*
>> + * Test sealing with active mmap()s
>> + * Modifying seals is only allowed if no other mmap() refs exist.
>> + */
>> +static void test_share_mmap(int fd)
>> +{
>> +	void *p;
>> +
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
>> +
>> +	/* shared/writable ref prevents sealing WRITE, but allows others */
>> +	p = SAFE_MMAP(NULL,
>> +			MFD_DEF_SIZE,
>> +			PROT_READ | PROT_WRITE,
>> +			MAP_SHARED,
>> +			fd,
>> +			0);
>> +	CHECK_RESULT(mfd_fail_add_seals(fd, F_SEAL_WRITE));
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
>> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_SHRINK));
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_SHRINK));
>> +	SAFE_MUNMAP(p, MFD_DEF_SIZE);
>> +
>> +	/* readable ref allows sealing */
>> +	p = SAFE_MMAP(NULL,
>> +			MFD_DEF_SIZE,
>> +			PROT_READ,
>> +			MAP_PRIVATE,
>> +			fd,
>> +			0);
>> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_WRITE));
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK));
>> +	SAFE_MUNMAP(p, MFD_DEF_SIZE);
>> +
>> +	tst_res(TPASS, "%s", __func__);
>> +}
>> +
>> +/*
>> + * Test sealing with open(/proc/self/fd/%d)
>> + * Via /proc we can get access to a separate file-context for the same memfd.
>> + * This is *not* like dup(), but like a real separate open(). Make sure the
>> + * semantics are as expected and we correctly check for RDONLY / WRONLY / RDWR.
>> + */
>> +static void test_share_open(int fd)
>> +{
>> +	int fd2;
>> +
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, 0));
>> +
>> +	fd2 = CHECK_RESULT(mfd_assert_open(fd, O_RDWR, 0));
>> +	CHECK_RESULT(mfd_assert_add_seals(fd, F_SEAL_WRITE));
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_WRITE));
>> +	CHECK_RESULT(mfd_assert_has_seals(fd2, F_SEAL_WRITE));
>> +
>> +	CHECK_RESULT(mfd_assert_add_seals(fd2, F_SEAL_SHRINK));
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK));
>> +	CHECK_RESULT(mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK));
>> +
>> +	SAFE_CLOSE(fd);
>> +	fd = CHECK_RESULT(mfd_assert_open(fd2, O_RDONLY, 0));
>> +
>> +	CHECK_RESULT(mfd_fail_add_seals(fd, F_SEAL_SEAL));
>> +	CHECK_RESULT(mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK));
>> +	CHECK_RESULT(mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK));
>> +
>> +	SAFE_CLOSE(fd2);
>> +
>> +	tst_res(TPASS, "%s", __func__);
>> +}
>> +
>> +static const struct tcase {
>> +	int flags;
>> +	void (*func)(int fd);
>> +} tcases[] = {
>> +	{MFD_ALLOW_SEALING, &test_basic},
>> +	{0,                 &test_no_sealing_without_flag},
>> +
>> +	{MFD_ALLOW_SEALING, &test_seal_write},
>> +	{MFD_ALLOW_SEALING, &test_seal_shrink},
>> +	{MFD_ALLOW_SEALING, &test_seal_grow},
>> +	{MFD_ALLOW_SEALING, &test_seal_resize},
>> +
>> +	{MFD_ALLOW_SEALING, &test_share_dup},
>> +	{MFD_ALLOW_SEALING, &test_share_mmap},
>> +	{MFD_ALLOW_SEALING, &test_share_open},
>> +};
>> +
>> +static void verify_memfd_create(unsigned int n)
>> +{
>> +	const struct tcase *tc;
>> +
>> +	tc = &tcases[n];
>> +
>> +	TEST(mfd_assert_new(TCID, MFD_DEF_SIZE, tc->flags));
>> +	if (TEST_RETURN < 0)
>> +		tst_brk(TBROK | TERRNO, "memfd_create() failed unexpectedly");
>> +
>> +	tc->func(TEST_RETURN);
>> +
>> +	if (TEST_RETURN > 0)
>> +		SAFE_CLOSE(TEST_RETURN);
>> +}
>> +
>> +static void setup(void)
>> +{
>> +	ASSERT_HAVE_MEMFD_CREATE();
>> +}
>> +
>> +static struct tst_test test = {
>> +	.tid = "memfd_create01",
>> +	.test = verify_memfd_create,
>> +	.tcnt = ARRAY_SIZE(tcases),
>> +	.setup = setup,
>> +};
>> diff --git a/testcases/kernel/syscalls/memfd_create/memfd_create_common.h b/testcases/kernel/syscalls/memfd_create/memfd_create_common.h
>> new file mode 100644
>> index 0000000..f07cc8c
>> --- /dev/null
>> +++ b/testcases/kernel/syscalls/memfd_create/memfd_create_common.h
>> @@ -0,0 +1,525 @@
>> +/*
>> + * Copyright (C) 2017  Red Hat, Inc.
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License as
>> + * published by the Free Software Foundation; either version 2 of
>> + * the License, or (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it would be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + */
>> +
>> +#ifndef MEMFD_TEST_COMMON
>> +#define MEMFD_TEST_COMMON
>> +
>> +#include <sys/types.h>
>> +#include <sys/syscall.h>
>> +#include <sys/uio.h>
>> +#include <lapi/fallocate.h>
>> +#include <lapi/fcntl.h>
>> +#include <lapi/memfd.h>
>> +#include <errno.h>
>> +#include <string.h>
>> +#include <stdio.h>
>> +#include <stdlib.h>
>> +#include <unistd.h>
>> +
>> +#define TST_NO_DEFAULT_MAIN
>> +#include <tst_test.h>
>> +
>> +#include "linux_syscall_numbers.h"
>> +
>> +#define MFD_DEF_SIZE 8192
>> +#define STACK_SIZE 65536
>> +
>> +enum assert_retval {
>> +	ALL_OK,
>> +	MEMFD_FAIL,
>> +	MEMFD_MISMATCH,
>> +	FTRUNCATE_FAIL,
>> +	FCNTL_FAIL,
>> +	GET_SEALS_MISMATCH,
>> +	ADD_SEALS_FAIL,
>> +	ADD_SEALS_MISMATCH,
>> +	FSTAT_FAIL,
>> +	FILE_SIZE_MISMATCH,
>> +	OPEN_MISMATCH,
>> +	OPEN_FAIL,
>> +	MPROTECT_FAIL,
>> +	FALLOCATE_PUNCH_FAIL,
>> +	WRITE_FAIL,
>> +	WRITE_MISMATCH,
>> +	MUNMAP_FAIL,
>> +	MMAP_FAIL,
>> +	MMAP_MISMATCH,
>> +	MMAP_MPROT_MISMATCH,
>> +	FALLOCATE_PUNCH_MISMATCH,
>> +	FTRUNCATE_SHRINK_MISMATCH,
>> +	FALLOCATE_ALLOC_FAIL,
>> +	FTRUNCATE_GROW_MISMATCH,
>> +	FALLOCATE_ALLOC_MISMATCH,
>> +	PWRITE_FAIL,
>> +	PWRITE_MISMATCH,
>> +	READ_FAIL,
>> +	READ_MISMATCH,
>> +	CLOSE_FAIL,
>> +};
>> +
>> +const char *err_msg[] = {
>> +	"all OK",
>> +	"memfd_create() failed",
>> +	"memfd_create() succeeded, but failure expected",
>> +	"ftruncate() failed",
>> +	"fcntl() failed",
>> +	"GET_SEALS() returned unexpected value",
>> +	"ADD_SEALS() failed",
>> +	"ADD_SEALS() didn't fail as expected",
>> +	"fstat() failed",
>> +	"wrong file size",
>> +	"open() didn't fail as expected",
>> +	"open() failed",
>> +	"mprotect() failed",
>> +	"fallocate(PUNCH_HOLE) failed",
>> +	"write() failed",
>> +	"write() didn't fail as expected",
>> +	"munmap() failed",
>> +	"mmap() failed",
>> +	"mmap() didn't fail as expected",
>> +	"mmap()+mprotect() didn't fail as expected",
>> +	"fallocate(PUNCH_HOLE) didn't fail as expected",
>> +	"ftruncate(SHRINK) didn't fail as expected",
>> +	"fallocate(ALLOC) failed",
>> +	"ftruncate(GROW) didn't fail as expected",
>> +	"fallocate(ALLOC) didn't fail as expected",
>> +	"pwrite() failed",
>> +	"pwrite() didn't fail as expected",
>> +	"read() failed",
>> +	"read() didn't fail as expected",
>> +	"close() failed",
>> +};
>> +
>> +#define STRINGIFY(A) #A
>> +
>> +#define CHECK_RESULT(func2call) ({ \
>> +	int result; \
>> +	result = func2call; \
>> +	if (result < ALL_OK) \
>> +		tst_brk(TFAIL, "%s: %s", STRINGIFY(func2call), \
>> +			err_msg[-result]); \
>> +	else \
>> +		tst_res(TPASS, "%s", STRINGIFY(func2call)); \
>> +	result; \
>> +})
>> +
>> +#define ASSERT_HAVE_MEMFD_CREATE() do { \
>> +	int r; \
>> +	r = mfd_assert_new("dummy_call", 0, 0); \
>> +	if (r < 0) \
>> +		tst_brk(TCONF, "memfd_create does not exist on your system."); \
>> +		SAFE_CLOSE(r); \
>                  ^
> 		The indentation here is confusing.
>
>> +	} while (0)
>> +
>> +static int sys_memfd_create(const char *name,
>> +		unsigned int flags)
>> +{
>> +	return syscall(__NR_memfd_create, name, flags);
>> +}
>> +
>> +static int mfd_assert_new(const char *name, loff_t sz, unsigned int flags)
>> +{
>> +	int fd, r;
>> +
>> +	fd = sys_memfd_create(name, flags);
>> +	if (fd < 0)
>> +		return -MEMFD_FAIL;
>> +
>> +	r = ftruncate(fd, sz);
>> +	if (r < 0)
>> +		return -FTRUNCATE_FAIL;
>> +
>> +	return fd;
>> +}
> This indirection (returning error number and matching it agains table is
> confusing as well).
>
> I wonder if we should do this similarily to safe macros, i.e. doing
> something as:
>
> #define SAFE_MFD_NEW(name, sz, flags) \
>          safe_mfd_new(__FILE__, __LINE__, name, flags);
>
> static int safe_mfd_new(const char *filename, const char lineno,
>                          const char *name, unsigned int flags)
> {
> 	int fd;
>
> 	if (sys_memfd_create(name, flags)) {
> 		tst_brk(TBROK | TERRNO,
> 		        "%s:%i: memfd_create(%s,%u) failed",
> 			file, lineno, name, flags);
> 	}
>
> 	return fd;
> }
>
> Then we could do something as:
>
> 	int fd;
>
> 	fd = SAFE_MFD_NEW("foo", 0);
> 	SAFE_FTRUNCATE(fd, sz);
>
> In the main test function, which seems to be much clearer code to me.
>
>> +static int mfd_fail_new(const char *name, unsigned int flags)
>> +{
>> +	int fd;
>> +
>> +	fd = sys_memfd_create(name, flags);
>> +	if (fd >= 0) {
>> +		close(fd);
>> +		return -MEMFD_MISMATCH;
>> +	}
>> +
>> +	return fd;
>> +}
>> +
>> +static int mfd_assert_get_seals(int fd)
>> +{
>> +	int r;
>> +
>> +	r = fcntl(fd, F_GET_SEALS);
>> +	if (r < 0)
>> +		return -FCNTL_FAIL;
>> +
>> +	return r;
>> +}
> This could be just replaced with SAFE_FCNTL() in the test code.
>
>> +static int mfd_assert_has_seals(int fd, int seals)
>> +{
>> +	int s;
>> +
>> +	s = mfd_assert_get_seals(fd);
>> +	if (s < 0)
>> +		return s;
>> +
>> +	if (s != seals)
>> +		return -GET_SEALS_MISMATCH;
>> +
>> +	return ALL_OK;
>> +}
> This as well, you can even just do:
>
> 	int s;
>
> 	s = SAFE_FCNTL(fd, F_GET_SEALS);
>
> 	if (seals != s) {
> 		tst_res(TFAIL, "Unexpected seals %i, expected %i",
> 		         seals, s);
> 	}
>
>> +static int mfd_assert_add_seals(int fd, int seals)
>> +{
>> +	int r;
>> +
>> +	r = mfd_assert_get_seals(fd);
>> +	if (r < 0)
>> +		return r;
>> +
>> +	r = fcntl(fd, F_ADD_SEALS, seals);
>> +	if (r < 0)
>> +		return -ADD_SEALS_FAIL;
>> +
>> +	return ALL_OK;
>> +}
> Again this is just one SAFE_FCNTL();
>
>> +static int mfd_fail_add_seals(int fd, int seals)
>> +{
>> +	int r;
>> +	int s;
>> +
>> +	r = fcntl(fd, F_GET_SEALS);
>> +	if (r < 0)
>> +		s = 0;
>> +	else
>> +		s = r;
> This does not make any sense, is the s variable used for anything at
> all?
>
>> +	r = fcntl(fd, F_ADD_SEALS, seals);
>> +	if (r >= 0)
>> +		return -ADD_SEALS_MISMATCH;
>> +
>> +	return ALL_OK;
>> +}
> And we can so something as:
>
> #define FAIL_ADD_SEALS(fd, seals) \
>          fail_add_seals(__FILE__, __LINE__, fd, seals)
>
> static void fail_add_seals(const char *file, const int lineno,
>                             int fd, int seals)
> {
> 	if (fcntl(fd, F_ADD_SEALS, seals) >= 0) {
> 		tst_res(TFAIL,
> 		        "%s:%i: fcntl(%i, F_ADD_SEALS, %i) passed unexpectedly",
> 			file, lineno, fd, seals);
> 	} else {
> 		tst_res(TPASS, "%s:%i: fcntl(%i, F_ADD_SEALS, %i) failed",
> 		        file, lineno, fd, seals);
> 	}
> }
>
> For the negative testcases.
>
>> +static int mfd_assert_size(int fd, size_t size)
>> +{
>> +	struct stat st;
>> +	int r;
>> +
>> +	r = fstat(fd, &st);
>> +	if (r < 0)
>> +		return -FSTAT_FAIL;
>> +	else if (st.st_size != (long)size)
>> +		return -FILE_SIZE_MISMATCH;
>> +
>> +	return ALL_OK;
>> +}
> We have SAFE_FSTAT() as well. etc.
>


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [LTP] [PATCH v2 5/6] syscalls: added memfd_create dir and memfd_create/memfd_create01.c
  2017-03-07 13:08     ` Jakub =?unknown-8bit?q?Ra=C4=8Dek?=
@ 2017-03-07 13:21       ` Cyril Hrubis
  0 siblings, 0 replies; 12+ messages in thread
From: Cyril Hrubis @ 2017-03-07 13:21 UTC (permalink / raw)
  To: ltp

Hi!
> SAFE_MFD_NEW and others should go to "include/tst_safe_macros.h", right?

That one is too big at this point. And I guess that this call would not
be usefull anywhere else than this testsuite, so having it in local
header should be fine.

> If I undestand this correctly, negative testcases will have to stay in
> memfd_create_common.h. That means I can't use
> SAFE_ macros in those functions/macros, as that would obscure line
> numbers. And putting those elsewhere would duplicate a lot of code.

Hmm, we can always use the functions SAFE_MACROS call and pass filename
and line number explicitly.

#define FAIL_MFD_FOO(foo, bar) \
	fail_mfd_foo(__FILE__, __LINE__, foo, bar)

void fail_mfd_foo(const char *file, const int lineno, int foo, int bar)
{
	int ret;

	ret = safe_foo(file, lineno, foo);

	...
}

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2017-03-07 13:21 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-06 17:45 [LTP] [PATCH v2 0/6] Added memfd_create() testsuite Jakub Racek
2017-03-06 17:45 ` [LTP] [PATCH v2 1/6] Added syscall numbers for memfd_create Jakub Racek
2017-03-06 17:45 ` [LTP] [PATCH v2 2/6] Added memfd_create() lapi flags Jakub Racek
2017-03-06 17:45 ` [LTP] [PATCH v2 3/6] Added fcntl() " Jakub Racek
2017-03-06 17:45 ` [LTP] [PATCH v2 4/6] Added fallocate() flags and wrapper to lapi Jakub Racek
2017-03-07 11:44   ` Cyril Hrubis
2017-03-06 17:45 ` [LTP] [PATCH v2 5/6] syscalls: added memfd_create dir and memfd_create/memfd_create01.c Jakub Racek
2017-03-07 12:17   ` Cyril Hrubis
2017-03-07 13:08     ` Jakub =?unknown-8bit?q?Ra=C4=8Dek?=
2017-03-07 13:21       ` Cyril Hrubis
2017-03-06 17:45 ` [LTP] [PATCH v2 6/6] syscalls/memfd_create02.c: added new test Jakub Racek
2017-03-07 12:21   ` Cyril Hrubis

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.