All of lore.kernel.org
 help / color / mirror / Atom feed
* [LTP] [PATCH v4 0/6] Added memfd_create() testsuite
@ 2017-03-15 16:35 Jakub Racek
  2017-03-15 16:35 ` [LTP] [PATCH v4 1/6] Added syscall numbers for memfd_create Jakub Racek
                   ` (5 more replies)
  0 siblings, 6 replies; 10+ messages in thread
From: Jakub Racek @ 2017-03-15 16:35 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. Code that runs _dup, _mmap and _open tests in
multi-threaded environment was not ported yet.

V2: fixed LTP style problems, added syscall numbers for each arch
V3: fixed more style problems, moved fallocate.h to include/lapi
V4:
    * fixed more style problems
    * fixed broken syscall availability detection

Jakub Racek (6):
  Added syscall numbers for memfd_create
  Added memfd_create() lapi flags
  Added fcntl() lapi flags
  move fallocate.h 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/fallocate/fallocate.h    |  70 ----
 testcases/kernel/syscalls/fallocate/fallocate01.c  |   2 +-
 testcases/kernel/syscalls/fallocate/fallocate02.c  |   2 +-
 testcases/kernel/syscalls/fallocate/fallocate03.c  |   2 +-
 testcases/kernel/syscalls/fallocate/fallocate04.c  |   2 +-
 testcases/kernel/syscalls/memfd_create/Makefile    |  19 +
 .../kernel/syscalls/memfd_create/memfd_create01.c  | 284 +++++++++++++
 .../kernel/syscalls/memfd_create/memfd_create02.c  |  92 +++++
 .../syscalls/memfd_create/memfd_create_common.h    | 457 +++++++++++++++++++++
 27 files changed, 992 insertions(+), 74 deletions(-)
 create mode 100644 include/lapi/fallocate.h
 create mode 100644 include/lapi/memfd.h
 delete mode 100644 testcases/kernel/syscalls/fallocate/fallocate.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] 10+ messages in thread

* [LTP] [PATCH v4 1/6] Added syscall numbers for memfd_create
  2017-03-15 16:35 [LTP] [PATCH v4 0/6] Added memfd_create() testsuite Jakub Racek
@ 2017-03-15 16:35 ` Jakub Racek
  2017-03-15 16:35 ` [LTP] [PATCH v4 2/6] Added memfd_create() lapi flags Jakub Racek
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Jakub Racek @ 2017-03-15 16:35 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] 10+ messages in thread

* [LTP] [PATCH v4 2/6] Added memfd_create() lapi flags
  2017-03-15 16:35 [LTP] [PATCH v4 0/6] Added memfd_create() testsuite Jakub Racek
  2017-03-15 16:35 ` [LTP] [PATCH v4 1/6] Added syscall numbers for memfd_create Jakub Racek
@ 2017-03-15 16:35 ` Jakub Racek
  2017-03-15 16:35 ` [LTP] [PATCH v4 3/6] Added fcntl() " Jakub Racek
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Jakub Racek @ 2017-03-15 16:35 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] 10+ messages in thread

* [LTP] [PATCH v4 3/6] Added fcntl() lapi flags
  2017-03-15 16:35 [LTP] [PATCH v4 0/6] Added memfd_create() testsuite Jakub Racek
  2017-03-15 16:35 ` [LTP] [PATCH v4 1/6] Added syscall numbers for memfd_create Jakub Racek
  2017-03-15 16:35 ` [LTP] [PATCH v4 2/6] Added memfd_create() lapi flags Jakub Racek
@ 2017-03-15 16:35 ` Jakub Racek
  2017-03-15 16:35 ` [LTP] [PATCH v4 4/6] move fallocate.h to lapi Jakub Racek
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Jakub Racek @ 2017-03-15 16:35 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] 10+ messages in thread

* [LTP] [PATCH v4 4/6] move fallocate.h to lapi
  2017-03-15 16:35 [LTP] [PATCH v4 0/6] Added memfd_create() testsuite Jakub Racek
                   ` (2 preceding siblings ...)
  2017-03-15 16:35 ` [LTP] [PATCH v4 3/6] Added fcntl() " Jakub Racek
@ 2017-03-15 16:35 ` Jakub Racek
  2017-03-15 16:35 ` [LTP] [PATCH v4 5/6] syscalls: added memfd_create dir and memfd_create/memfd_create01.c Jakub Racek
  2017-03-15 16:35 ` [LTP] [PATCH v4 6/6] syscalls/memfd_create02.c: added new test Jakub Racek
  5 siblings, 0 replies; 10+ messages in thread
From: Jakub Racek @ 2017-03-15 16:35 UTC (permalink / raw)
  To: ltp

Signed-off-by: Jakub Racek <jracek@redhat.com>
---
 include/lapi/fallocate.h                          | 66 +++++++++++++++++++++
 testcases/kernel/syscalls/fallocate/fallocate.h   | 70 -----------------------
 testcases/kernel/syscalls/fallocate/fallocate01.c |  2 +-
 testcases/kernel/syscalls/fallocate/fallocate02.c |  2 +-
 testcases/kernel/syscalls/fallocate/fallocate03.c |  2 +-
 testcases/kernel/syscalls/fallocate/fallocate04.c |  2 +-
 6 files changed, 70 insertions(+), 74 deletions(-)
 create mode 100644 include/lapi/fallocate.h
 delete mode 100644 testcases/kernel/syscalls/fallocate/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 */
diff --git a/testcases/kernel/syscalls/fallocate/fallocate.h b/testcases/kernel/syscalls/fallocate/fallocate.h
deleted file mode 100644
index 5119988..0000000
--- a/testcases/kernel/syscalls/fallocate/fallocate.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#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 */
diff --git a/testcases/kernel/syscalls/fallocate/fallocate01.c b/testcases/kernel/syscalls/fallocate/fallocate01.c
index c99e799..89ce996 100644
--- a/testcases/kernel/syscalls/fallocate/fallocate01.c
+++ b/testcases/kernel/syscalls/fallocate/fallocate01.c
@@ -100,7 +100,7 @@
 #include <sys/utsname.h>
 
 #include "test.h"
-#include "fallocate.h"
+#include "lapi/fallocate.h"
 #include "lapi/fcntl.h"
 
 #define BLOCKS_WRITTEN 12
diff --git a/testcases/kernel/syscalls/fallocate/fallocate02.c b/testcases/kernel/syscalls/fallocate/fallocate02.c
index ba37796..bee0863 100644
--- a/testcases/kernel/syscalls/fallocate/fallocate02.c
+++ b/testcases/kernel/syscalls/fallocate/fallocate02.c
@@ -39,7 +39,7 @@
 
 #include "test.h"
 #include "safe_macros.h"
-#include "fallocate.h"
+#include "lapi/fallocate.h"
 
 #define BLOCKS_WRITTEN		12
 #ifdef TEST_DEFAULT
diff --git a/testcases/kernel/syscalls/fallocate/fallocate03.c b/testcases/kernel/syscalls/fallocate/fallocate03.c
index 092d2bb..d73d07d 100644
--- a/testcases/kernel/syscalls/fallocate/fallocate03.c
+++ b/testcases/kernel/syscalls/fallocate/fallocate03.c
@@ -96,7 +96,7 @@
 #include <sys/utsname.h>
 
 #include "test.h"
-#include "fallocate.h"
+#include "lapi/fallocate.h"
 
 #define BLOCKS_WRITTEN 12
 #define HOLE_SIZE_IN_BLOCKS 12
diff --git a/testcases/kernel/syscalls/fallocate/fallocate04.c b/testcases/kernel/syscalls/fallocate/fallocate04.c
index f204188..a672916 100644
--- a/testcases/kernel/syscalls/fallocate/fallocate04.c
+++ b/testcases/kernel/syscalls/fallocate/fallocate04.c
@@ -32,7 +32,7 @@
 
 #include "test.h"
 #include "safe_macros.h"
-#include "fallocate.h"
+#include "lapi/fallocate.h"
 
 char *TCID = "fallocate04";
 int TST_TOTAL = 5;
-- 
1.8.3.1


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

* [LTP] [PATCH v4 5/6] syscalls: added memfd_create dir and memfd_create/memfd_create01.c
  2017-03-15 16:35 [LTP] [PATCH v4 0/6] Added memfd_create() testsuite Jakub Racek
                   ` (3 preceding siblings ...)
  2017-03-15 16:35 ` [LTP] [PATCH v4 4/6] move fallocate.h to lapi Jakub Racek
@ 2017-03-15 16:35 ` Jakub Racek
  2017-03-21 15:27   ` Cyril Hrubis
  2017-03-22 10:19   ` Cyril Hrubis
  2017-03-15 16:35 ` [LTP] [PATCH v4 6/6] syscalls/memfd_create02.c: added new test Jakub Racek
  5 siblings, 2 replies; 10+ messages in thread
From: Jakub Racek @ 2017-03-15 16:35 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  | 284 +++++++++++++
 .../syscalls/memfd_create/memfd_create_common.h    | 457 +++++++++++++++++++++
 5 files changed, 763 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 89abac5..d2e0a73 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..8e560ac
--- /dev/null
+++ b/testcases/kernel/syscalls/memfd_create/memfd_create01.c
@@ -0,0 +1,284 @@
+/*
+ * 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_MFD_HAS_SEALS(fd, 0);
+	CHECK_MFD_ADD_SEALS(fd, F_SEAL_SHRINK | F_SEAL_WRITE);
+	CHECK_MFD_HAS_SEALS(fd, F_SEAL_SHRINK | F_SEAL_WRITE);
+
+	/* add them again */
+	CHECK_MFD_ADD_SEALS(fd, F_SEAL_SHRINK | F_SEAL_WRITE);
+	CHECK_MFD_HAS_SEALS(fd, F_SEAL_SHRINK | F_SEAL_WRITE);
+
+	/* add more seals and seal against sealing */
+	CHECK_MFD_ADD_SEALS(fd, F_SEAL_GROW | F_SEAL_SEAL);
+	CHECK_MFD_HAS_SEALS(fd, F_SEAL_SHRINK | F_SEAL_GROW |
+			F_SEAL_WRITE | F_SEAL_SEAL);
+
+	/* verify that sealing no longer works */
+	CHECK_MFD_FAIL_ADD_SEALS(fd, F_SEAL_GROW);
+	CHECK_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_MFD_HAS_SEALS(fd, F_SEAL_SEAL);
+	CHECK_MFD_FAIL_ADD_SEALS(fd,
+			F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE);
+	CHECK_MFD_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_MFD_HAS_SEALS(fd, 0);
+	CHECK_MFD_ADD_SEALS(fd, F_SEAL_WRITE);
+	CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE);
+
+	CHECK_MFD_READABLE(fd);
+	CHECK_MFD_NON_WRITEABLE(fd);
+	CHECK_MFD_SHRINKABLE(fd);
+	CHECK_MFD_GROWABLE(fd);
+	CHECK_NON_GROWABLE_BY_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_MFD_HAS_SEALS(fd, 0);
+	CHECK_MFD_ADD_SEALS(fd, F_SEAL_SHRINK);
+	CHECK_MFD_HAS_SEALS(fd, F_SEAL_SHRINK);
+
+	CHECK_MFD_READABLE(fd);
+	CHECK_MFD_WRITEABLE(fd);
+	CHECK_MFD_NON_SHRINKABLE(fd);
+	CHECK_MFD_GROWABLE(fd);
+	CHECK_GROWABLE_BY_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_MFD_HAS_SEALS(fd, 0);
+	CHECK_MFD_ADD_SEALS(fd, F_SEAL_GROW);
+	CHECK_MFD_HAS_SEALS(fd, F_SEAL_GROW);
+
+	CHECK_MFD_READABLE(fd);
+	CHECK_MFD_WRITEABLE(fd);
+	CHECK_MFD_SHRINKABLE(fd);
+	CHECK_MFD_NON_GROWABLE(fd);
+	CHECK_NON_GROWABLE_BY_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_MFD_HAS_SEALS(fd, 0);
+	CHECK_MFD_ADD_SEALS(fd, F_SEAL_SHRINK | F_SEAL_GROW);
+	CHECK_MFD_HAS_SEALS(fd, F_SEAL_SHRINK | F_SEAL_GROW);
+
+	CHECK_MFD_READABLE(fd);
+	CHECK_MFD_WRITEABLE(fd);
+	CHECK_MFD_NON_SHRINKABLE(fd);
+	CHECK_MFD_NON_GROWABLE(fd);
+	CHECK_NON_GROWABLE_BY_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_MFD_HAS_SEALS(fd, 0);
+
+	fd2 = SAFE_DUP(fd);
+	CHECK_MFD_HAS_SEALS(fd2, 0);
+
+	CHECK_MFD_ADD_SEALS(fd, F_SEAL_WRITE);
+	CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE);
+	CHECK_MFD_HAS_SEALS(fd2, F_SEAL_WRITE);
+
+	CHECK_MFD_ADD_SEALS(fd2, F_SEAL_SHRINK);
+	CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
+	CHECK_MFD_HAS_SEALS(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
+
+	CHECK_MFD_ADD_SEALS(fd, F_SEAL_SEAL);
+	CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
+	CHECK_MFD_HAS_SEALS(fd2, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
+
+	CHECK_MFD_FAIL_ADD_SEALS(fd, F_SEAL_GROW);
+	CHECK_MFD_FAIL_ADD_SEALS(fd2, F_SEAL_GROW);
+	CHECK_MFD_FAIL_ADD_SEALS(fd, F_SEAL_SEAL);
+	CHECK_MFD_FAIL_ADD_SEALS(fd2, F_SEAL_SEAL);
+
+	SAFE_CLOSE(fd2);
+
+	CHECK_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_MFD_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_MFD_FAIL_ADD_SEALS(fd, F_SEAL_WRITE);
+	CHECK_MFD_HAS_SEALS(fd, 0);
+	CHECK_MFD_ADD_SEALS(fd, F_SEAL_SHRINK);
+	CHECK_MFD_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_MFD_ADD_SEALS(fd, F_SEAL_WRITE);
+	CHECK_MFD_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_MFD_HAS_SEALS(fd, 0);
+
+	fd2 = CHECK_MFD_OPEN(fd, O_RDWR, 0);
+	CHECK_MFD_ADD_SEALS(fd, F_SEAL_WRITE);
+	CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE);
+	CHECK_MFD_HAS_SEALS(fd2, F_SEAL_WRITE);
+
+	CHECK_MFD_ADD_SEALS(fd2, F_SEAL_SHRINK);
+	CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
+	CHECK_MFD_HAS_SEALS(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
+
+	SAFE_CLOSE(fd);
+	fd = CHECK_MFD_OPEN(fd2, O_RDONLY, 0);
+
+	CHECK_MFD_FAIL_ADD_SEALS(fd, F_SEAL_SEAL);
+	CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
+	CHECK_MFD_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)
+{
+	int fd;
+	const struct tcase *tc;
+
+	tc = &tcases[n];
+
+	fd = CHECK_MFD_NEW(TCID, MFD_DEF_SIZE, tc->flags);
+
+	tc->func(fd);
+
+	SAFE_CLOSE(fd);
+}
+
+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..71f4123
--- /dev/null
+++ b/testcases/kernel/syscalls/memfd_create/memfd_create_common.h
@@ -0,0 +1,457 @@
+/*
+ * 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
+
+static int sys_memfd_create(const char *name, unsigned int flags)
+{
+	return tst_syscall(__NR_memfd_create, name, flags);
+}
+
+static void check_ftruncate(const char *filename, const int lineno,
+		int fd, off_t length)
+{
+	safe_ftruncate(filename, lineno, fd, length);
+
+	tst_res_(filename, lineno, TPASS,
+			"ftruncate(%d, %ld) succeeded", fd, length);
+}
+
+static void check_ftruncate_fail(const char *filename, const int lineno,
+		int fd, off_t length)
+{
+	if (ftruncate(fd, length) >= 0)
+		tst_brk_(filename, lineno, TFAIL,
+				"ftruncate(%d, %ld) succeeded unexpectedly",
+				fd, length);
+
+	tst_res_(filename, lineno, TPASS | TERRNO,
+			"ftruncate(%d, %ld) failed as expected", fd, length);
+}
+
+#define CHECK_MFD_NEW(name, sz, flags) \
+	check_mfd_new(__FILE__, __LINE__, name, (sz), (flags))
+
+static int check_mfd_new(const char *filename, const int lineno,
+		const char *name, loff_t sz, int flags)
+{
+	int fd;
+
+	fd = sys_memfd_create(name, flags);
+	if (fd < 0)
+		tst_brk_(filename, lineno, TBROK | TERRNO,
+				"memfd_create(%s, %d) failed", name, flags);
+	tst_res_(filename, lineno, TPASS, "memfd_create(%s, %d) succeeded",
+			name, flags);
+
+	check_ftruncate(filename, lineno, fd, sz);
+
+	return fd;
+}
+
+static int check_fallocate(const char *filename, const int lineno,
+		int fd, int mode, off_t offset, off_t len)
+{
+	int r;
+
+	r = fallocate(fd, mode, offset, len);
+	if (r < 0)
+		tst_brk_(filename, lineno, TFAIL | TERRNO,
+				"fallocate(%d, %d, %ld, %ld) failed",
+				fd, mode, offset, len);
+
+	tst_res_(filename, lineno, TPASS,
+			"fallocate(%d, %d, %ld, %ld) succeeded",
+			fd, mode, offset, len);
+
+	return r;
+}
+
+static int check_fallocate_fail(const char *filename, const int lineno,
+		int fd, int mode, off_t offset, off_t len)
+{
+	int r;
+
+	r = fallocate(fd, mode, offset, len);
+	if (r >= 0)
+		tst_brk_(filename, lineno, TFAIL,
+			"fallocate(%d, %d, %ld, %ld) succeeded unexpectedly",
+			fd, mode, offset, len);
+
+	tst_res_(filename, lineno, TPASS | TERRNO,
+			"fallocate(%d, %d, %ld, %ld) failed as expected",
+			fd, mode, offset, len);
+
+	return r;
+}
+
+#define ASSERT_HAVE_MEMFD_CREATE() \
+	assert_have_memfd_create(__FILE__, __LINE__)
+
+void assert_have_memfd_create(const char *filename, const int lineno)
+{
+	int flags;
+
+	TEST(sys_memfd_create("dummy_call", 0));
+	if (TEST_RETURN < 0) {
+		flags = ((TERRNO == -ENOSYS ||
+			TERRNO == -EINVAL) ? TCONF : TBROK) | TERRNO;
+		tst_brk_(filename, lineno, flags, "memfd_create() failed");
+	}
+
+	SAFE_CLOSE(TEST_RETURN);
+}
+
+
+#define CHECK_MFD_FAIL_NEW(name, flags) \
+	do { \
+		int fd; \
+		fd = sys_memfd_create((name), (flags)); \
+		if (fd >= 0) { \
+			safe_close(__FILE__, __LINE__, NULL, fd); \
+			tst_brk(TFAIL, \
+				"memfd_create(%s, %d) succeeded unexpectedly",\
+				(name), (flags)); \
+		} \
+		tst_res_(__FILE__, __LINE__, TPASS | TERRNO, \
+			"memfd_create(%s, %d) failed as expected", \
+			(name), (flags)) \
+	} while (0)
+
+#define CHECK_MMAP_FAIL(addr, length, prot, flags, fd, offset) \
+	check_mmap_fail(__FILE__, __LINE__, (addr), (length), (prot), \
+			(flags), (fd), (offset))
+
+void check_mmap_fail(const char *file, const int lineno, void *addr,
+		size_t length, int prot, int flags, int fd, off_t offset)
+{
+	if (mmap(addr, length, prot, flags, fd, offset) != MAP_FAILED) {
+		tst_brk_(file, lineno, TFAIL,
+			"mmap(%p, %zu, %i, %i, %i, %zi) succeeded unexpectedly",
+			addr, length, prot, flags, fd, offset);
+	}
+
+	tst_res_(file, lineno, TPASS | TERRNO,
+			"mmap(%p, %zu, %i, %i, %i, %zi) failed as expected",
+			addr, length, prot, flags, fd, offset);
+}
+
+#define CHECK_MMAP(addr, length, prot, flags, fd, offset) \
+	check_mmap(__FILE__, __LINE__, (addr), (length), (prot), \
+			(flags), (fd), (offset))
+
+void *check_mmap(const char *file, const int lineno, void *addr,
+		size_t length, int prot, int flags, int fd, off_t offset)
+{
+	void *p;
+
+	p = safe_mmap(file, lineno, addr, length, prot, flags, fd, offset);
+
+	tst_res_(file, lineno, TPASS,
+			"mmap(%p, %zu, %i, %i, %i, %zi) succeeded",
+			addr, length, prot, flags, fd, offset);
+
+	return p;
+}
+
+#define CHECK_MUNMAP(p, length) \
+	check_munmap(__FILE__, __LINE__, (p), (length))
+
+void check_munmap(const char *file, const int lineno, void *p, size_t length)
+{
+	safe_munmap(file, lineno, NULL, p, length);
+	tst_res_(file, lineno, TPASS, "munmap(%p, %ld) succeeded",
+			p, length);
+}
+
+void check_mprotect(const char *file, const int lineno, void *addr,
+		size_t length, int prot)
+{
+	if (mprotect(addr, length, prot) < 0)
+		tst_brk_(file, lineno, TFAIL | TERRNO,
+			"mprotect(%p, %ld, %d) failed", addr, length, prot);
+
+	tst_res_(file, lineno, TPASS,
+			"mprotect(%p, %ld, %d) succeeded", addr, length, prot);
+}
+
+#define CHECK_MFD_GET_SEALS(fd) \
+	({int r = SAFE_FCNTL((fd), F_GET_SEALS); \
+	 tst_res(TPASS, "fcntl(%d, F_GET_SEALS) succeeded", (fd)); r; })
+
+#define CHECK_MFD_HAS_SEALS(fd, seals) \
+	do { \
+		if (CHECK_MFD_GET_SEALS((fd)) != (seals)) \
+		tst_brk(TFAIL, "fd %d doesn't have expected seals", (fd)); \
+		tst_res(TPASS, "fd %d has expected seals", (fd)); \
+	} while (0)
+
+#define CHECK_MFD_ADD_SEALS(fd, seals) \
+	({int r = SAFE_FCNTL((fd), F_ADD_SEALS, (seals)); \
+	 tst_res(TPASS, "fcntl(%d, F_ADD_SEALS, %d) succeeded", \
+		 (fd), (seals)); r; })
+
+#define CHECK_MFD_FAIL_ADD_SEALS(fd, seals) \
+	do { \
+		if (fcntl((fd), F_ADD_SEALS, (seals)) >= 0) \
+		tst_brk(TFAIL, \
+			"fcntl(%d, F_ADD_SEALS) succeeded unexpectedly", \
+			(fd)); \
+		tst_res(TPASS | TERRNO, \
+			"fcntl(%d, F_ADD_SEALS, %d) failed as expected", \
+				(fd), (seals)); \
+	} while (0)
+
+#define CHECK_MFD_SIZE(fd, size) \
+	check_mfd_size(__FILE__, __LINE__, (fd), (size))
+
+static void check_mfd_size(const char *filename, const int lineno,
+		int fd, size_t size)
+{
+	struct stat st;
+
+	safe_fstat(filename, lineno, fd, &st);
+
+	if (st.st_size != (long)size)
+		tst_brk_(filename, lineno, TFAIL,
+				"fstat(%d, &st): unexpected file size", fd);
+
+	tst_res_(filename, lineno, TPASS,
+			"fstat(%d, &st): file size is correct", fd);
+}
+
+#define CHECK_MFD_OPEN(fd, flags, mode) \
+	check_mfd_open(__FILE__, __LINE__, (fd), (flags), (mode))
+
+static int check_mfd_open(const char *filename, const int lineno, int fd,
+		int flags, mode_t mode)
+{
+	int r;
+	char buf[512];
+
+	sprintf(buf, "/proc/self/fd/%d", fd);
+
+	r = safe_open(filename, lineno, NULL, buf, flags, mode);
+	tst_res_(filename, lineno, TPASS, "open(%s, %d, %d) succeeded",
+			buf, flags, mode);
+
+	return r;
+}
+
+#define CHECK_MFD_FAIL_OPEN(fd, flags, mode) \
+	do { \
+		char buf[512]; \
+		sprintf(buf, "/proc/self/fd/%d", (fd)); \
+		if (open(buf, (flags), (mode)) >= 0) \
+		tst_brk(TFAIL, "open(%s, %d, %d) succeeded unexpectedly",\
+				buf, (flags), (mode)); \
+		tst_res(TPASS | TERRNO, "open(%s, %d, %d) failed as expected",\
+				buf, (flags), (mode));\
+	} while (0)
+
+#define CHECK_MFD_READABLE(fd) \
+	check_mfd_readable(__FILE__, __LINE__, (fd))
+
+static void check_mfd_readable(const char *filename, const int lineno, int fd)
+{
+	char buf[16];
+	void *p;
+
+	safe_read(filename, lineno, NULL, 1, fd, buf, sizeof(buf));
+	tst_res_(filename, lineno, TPASS, "read(%d, %s, %ld) succeeded",
+			fd, buf, sizeof(buf));
+
+	/* verify PROT_READ *is* allowed */
+	p = check_mmap(filename, lineno, NULL, MFD_DEF_SIZE,
+			PROT_READ, MAP_PRIVATE, fd, 0);
+
+	check_munmap(filename, lineno, p, MFD_DEF_SIZE);
+
+	/* verify MAP_PRIVATE is *always* allowed (even writable) */
+	p = check_mmap(filename, lineno, NULL, MFD_DEF_SIZE,
+			PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+
+	check_munmap(filename, lineno, p, MFD_DEF_SIZE);
+}
+
+#define CHECK_MFD_WRITEABLE(fd) \
+	check_mfd_writeable(__FILE__, __LINE__, (fd))
+
+static void check_mfd_writeable(const char *filename,
+		const int lineno, int fd)
+{
+	void *p;
+
+	/* verify write() succeeds */
+	safe_write(filename, lineno, NULL, 1, fd, "\0\0\0\0", 4);
+	tst_res_(filename, lineno, TPASS, "write(%d, %p, %d) succeeded",
+			fd, "\0\0\0\0", 4);
+
+	/* verify PROT_READ | PROT_WRITE is allowed */
+	p = check_mmap(filename, lineno, NULL, MFD_DEF_SIZE,
+			PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+
+	*(char *)p = 0;
+	check_munmap(filename, lineno, p, MFD_DEF_SIZE);
+
+	/* verify PROT_WRITE is allowed */
+	p = check_mmap(filename, lineno, NULL, MFD_DEF_SIZE,
+			PROT_WRITE, MAP_SHARED, fd, 0);
+
+	*(char *)p = 0;
+	check_munmap(filename, lineno, p, MFD_DEF_SIZE);
+
+	/* verify PROT_READ with MAP_SHARED is allowed and a following
+	 * mprotect(PROT_WRITE) allows writing
+	 */
+	p = check_mmap(filename, lineno, NULL, MFD_DEF_SIZE,
+			PROT_READ, MAP_SHARED, fd, 0);
+
+	check_mprotect(filename, lineno, p, MFD_DEF_SIZE,
+			PROT_READ | PROT_WRITE);
+
+	*(char *)p = 0;
+	check_munmap(filename, lineno, p, MFD_DEF_SIZE);
+
+	/* verify PUNCH_HOLE works */
+	check_fallocate(filename, lineno, fd,
+			FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
+			0, MFD_DEF_SIZE);
+}
+
+#define CHECK_MFD_NON_WRITEABLE(fd) \
+	check_mfd_non_writeable(__FILE__, __LINE__, (fd))
+
+static void check_mfd_non_writeable(const char *filename,
+		const int lineno, int fd)
+{
+	ssize_t l;
+	void *p;
+
+	/* verify write() fails */
+	l = write(fd, "data", 4);
+	if (l != -EPERM)
+		tst_brk(TFAIL | TERRNO, "write() didn't fail as expected");
+
+	/* verify PROT_READ | PROT_WRITE is not allowed */
+	check_mmap_fail(filename, lineno, NULL, MFD_DEF_SIZE,
+			PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+
+	/* verify PROT_WRITE is not allowed */
+	check_mmap_fail(filename, lineno, NULL, MFD_DEF_SIZE,
+			PROT_WRITE, MAP_SHARED, fd, 0);
+
+	/* 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) {
+		if (mprotect(p, MFD_DEF_SIZE, PROT_READ | PROT_WRITE) >= 0)
+			tst_brk(TFAIL | TERRNO,
+				"mmap()+mprotect() succeeded unexpectedly");
+	}
+
+	/* verify PUNCH_HOLE fails */
+	check_fallocate_fail(filename, lineno, fd,
+		FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, MFD_DEF_SIZE);
+}
+
+#define CHECK_MFD_SHRINKABLE(fd) \
+	check_mfd_shrinkable(__FILE__, __LINE__, (fd))
+
+static void check_mfd_shrinkable(const char *filename,
+				const int lineno, int fd)
+{
+	int fd2;
+
+	check_ftruncate(filename, lineno, fd, MFD_DEF_SIZE / 2);
+	check_mfd_size(filename, lineno, fd, MFD_DEF_SIZE / 2);
+
+	fd2 = check_mfd_open(filename, lineno, fd,
+			O_RDWR | O_CREAT | O_TRUNC, 0600);
+	safe_close(filename, lineno, NULL, fd2);
+
+	check_mfd_size(filename, lineno, fd, 0);
+}
+
+#define CHECK_MFD_NON_SHRINKABLE(fd) \
+	do { \
+		check_ftruncate_fail(__FILE__, __LINE__, (fd), \
+				MFD_DEF_SIZE / 2); \
+		CHECK_MFD_FAIL_OPEN((fd), (O_RDWR | O_CREAT | O_TRUNC), 0600);\
+	} while (0)
+
+#define CHECK_MFD_GROWABLE(fd) \
+	check_mfd_growable(__FILE__, __LINE__, (fd))
+
+static void check_mfd_growable(const char *filename, const int lineno, int fd)
+{
+	check_ftruncate(filename, lineno, fd, MFD_DEF_SIZE * 2);
+	check_mfd_size(filename, lineno, fd, MFD_DEF_SIZE * 2);
+
+	check_fallocate(filename, lineno, fd, 0, 0, MFD_DEF_SIZE * 4);
+	check_mfd_size(filename, lineno, fd, MFD_DEF_SIZE * 4);
+}
+
+#define CHECK_MFD_NON_GROWABLE(fd) \
+	do { \
+		check_ftruncate_fail(__FILE__, __LINE__, fd, \
+				MFD_DEF_SIZE * 2); \
+		check_fallocate_fail(__FILE__, __LINE__, fd, \
+				0, 0, MFD_DEF_SIZE * 4); \
+	} while (0)
+
+#define CHECK_GROWABLE_BY_WRITE(fd) \
+	do {\
+		char buf[MFD_DEF_SIZE * 8]; \
+		if (pwrite((fd), buf, sizeof(buf), 0) != sizeof(buf)) \
+		tst_brk(TFAIL | TERRNO, "pwrite(%d, %s, %ld, %d) failed", \
+				(fd), buf, sizeof(buf), 0); \
+		tst_res(TPASS, "pwrite(%d, %s, %ld, %d) succeeded", \
+				(fd), buf, sizeof(buf), 0); \
+		check_mfd_size(__FILE__, __LINE__, (fd), MFD_DEF_SIZE * 8); \
+	} while (0)
+
+#define CHECK_NON_GROWABLE_BY_WRITE(fd) \
+	do { \
+		char buf[MFD_DEF_SIZE * 8]; \
+		if (pwrite((fd), buf, sizeof(buf), 0) == sizeof(buf)) \
+		tst_brk(TFAIL, \
+			"pwrite(%d, %s, %ld, %d) didn't fail as expected", \
+			(fd), buf, sizeof(buf), 0); \
+	} while (0)
+
+#endif
-- 
1.8.3.1


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

* [LTP] [PATCH v4 6/6] syscalls/memfd_create02.c: added new test
  2017-03-15 16:35 [LTP] [PATCH v4 0/6] Added memfd_create() testsuite Jakub Racek
                   ` (4 preceding siblings ...)
  2017-03-15 16:35 ` [LTP] [PATCH v4 5/6] syscalls: added memfd_create dir and memfd_create/memfd_create01.c Jakub Racek
@ 2017-03-15 16:35 ` Jakub Racek
  5 siblings, 0 replies; 10+ messages in thread
From: Jakub Racek @ 2017-03-15 16:35 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 d2e0a73..d998411 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..a6d76d4
--- /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(sys_memfd_create(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] 10+ messages in thread

* [LTP] [PATCH v4 5/6] syscalls: added memfd_create dir and memfd_create/memfd_create01.c
  2017-03-15 16:35 ` [LTP] [PATCH v4 5/6] syscalls: added memfd_create dir and memfd_create/memfd_create01.c Jakub Racek
@ 2017-03-21 15:27   ` Cyril Hrubis
  2017-03-21 17:46     ` Jakub =?unknown-8bit?q?Ra=C4=8Dek?=
  2017-03-22 10:19   ` Cyril Hrubis
  1 sibling, 1 reply; 10+ messages in thread
From: Cyril Hrubis @ 2017-03-21 15:27 UTC (permalink / raw)
  To: ltp

Hi!
>  .../syscalls/memfd_create/memfd_create_common.h    | 457 +++++++++++++++++++++

Just a short question before further review, do you intend to write more
testcases that will use this header?

Since as it is the memfd_create02 needs only the memfd_new function and
the ASSERT that memfd_create() is implemented in kernel and including
that header in memfd_create02.c yields a few "unused function" warnings.
There are a couple of ways how to fix that but the easies solution would
be moving these functions into the memfd_create01.c in a case that
these are not needed for further testcases.

-- 
Cyril Hrubis
chrubis@suse.cz

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

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

Hi,

actually yes, I would like to add some other tests. The multiprocessing 
tests are missing for now. This is because I didn't like how it is done
in original testsuite, and also this patchset seems large enough already.

Thanks!

On 03/21/2017 04:27 PM, Cyril Hrubis wrote:
> Hi!
>>  .../syscalls/memfd_create/memfd_create_common.h    | 457 +++++++++++++++++++++
>
> Just a short question before further review, do you intend to write more
> testcases that will use this header?
>
> Since as it is the memfd_create02 needs only the memfd_new function and
> the ASSERT that memfd_create() is implemented in kernel and including
> that header in memfd_create02.c yields a few "unused function" warnings.
> There are a couple of ways how to fix that but the easies solution would
> be moving these functions into the memfd_create01.c in a case that
> these are not needed for further testcases.
>

-- 
Regards,
     Jakub

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

* [LTP] [PATCH v4 5/6] syscalls: added memfd_create dir and memfd_create/memfd_create01.c
  2017-03-15 16:35 ` [LTP] [PATCH v4 5/6] syscalls: added memfd_create dir and memfd_create/memfd_create01.c Jakub Racek
  2017-03-21 15:27   ` Cyril Hrubis
@ 2017-03-22 10:19   ` Cyril Hrubis
  1 sibling, 0 replies; 10+ messages in thread
From: Cyril Hrubis @ 2017-03-22 10:19 UTC (permalink / raw)
  To: ltp

Hi!
> --- /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..8e560ac
> --- /dev/null
> +++ b/testcases/kernel/syscalls/memfd_create/memfd_create01.c
> @@ -0,0 +1,284 @@
> +/*
> + * 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_MFD_HAS_SEALS(fd, 0);
> +	CHECK_MFD_ADD_SEALS(fd, F_SEAL_SHRINK | F_SEAL_WRITE);
> +	CHECK_MFD_HAS_SEALS(fd, F_SEAL_SHRINK | F_SEAL_WRITE);
> +
> +	/* add them again */
> +	CHECK_MFD_ADD_SEALS(fd, F_SEAL_SHRINK | F_SEAL_WRITE);
> +	CHECK_MFD_HAS_SEALS(fd, F_SEAL_SHRINK | F_SEAL_WRITE);
> +
> +	/* add more seals and seal against sealing */
> +	CHECK_MFD_ADD_SEALS(fd, F_SEAL_GROW | F_SEAL_SEAL);
> +	CHECK_MFD_HAS_SEALS(fd, F_SEAL_SHRINK | F_SEAL_GROW |
> +			F_SEAL_WRITE | F_SEAL_SEAL);
> +
> +	/* verify that sealing no longer works */
> +	CHECK_MFD_FAIL_ADD_SEALS(fd, F_SEAL_GROW);
> +	CHECK_MFD_FAIL_ADD_SEALS(fd, 0);
> +
> +	tst_res(TPASS, "%s", __func__);

There is no resason to print these additional PASS messages at the end
of the test function now.

> +}
> +
> +/*
> + * 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_MFD_HAS_SEALS(fd, F_SEAL_SEAL);
> +	CHECK_MFD_FAIL_ADD_SEALS(fd,
> +			F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE);
> +	CHECK_MFD_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_MFD_HAS_SEALS(fd, 0);
> +	CHECK_MFD_ADD_SEALS(fd, F_SEAL_WRITE);
> +	CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE);
> +
> +	CHECK_MFD_READABLE(fd);
> +	CHECK_MFD_NON_WRITEABLE(fd);
> +	CHECK_MFD_SHRINKABLE(fd);
> +	CHECK_MFD_GROWABLE(fd);
> +	CHECK_NON_GROWABLE_BY_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_MFD_HAS_SEALS(fd, 0);
> +	CHECK_MFD_ADD_SEALS(fd, F_SEAL_SHRINK);
> +	CHECK_MFD_HAS_SEALS(fd, F_SEAL_SHRINK);
> +
> +	CHECK_MFD_READABLE(fd);
> +	CHECK_MFD_WRITEABLE(fd);
> +	CHECK_MFD_NON_SHRINKABLE(fd);
> +	CHECK_MFD_GROWABLE(fd);
> +	CHECK_GROWABLE_BY_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_MFD_HAS_SEALS(fd, 0);
> +	CHECK_MFD_ADD_SEALS(fd, F_SEAL_GROW);
> +	CHECK_MFD_HAS_SEALS(fd, F_SEAL_GROW);
> +
> +	CHECK_MFD_READABLE(fd);
> +	CHECK_MFD_WRITEABLE(fd);
> +	CHECK_MFD_SHRINKABLE(fd);
> +	CHECK_MFD_NON_GROWABLE(fd);
> +	CHECK_NON_GROWABLE_BY_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_MFD_HAS_SEALS(fd, 0);
> +	CHECK_MFD_ADD_SEALS(fd, F_SEAL_SHRINK | F_SEAL_GROW);
> +	CHECK_MFD_HAS_SEALS(fd, F_SEAL_SHRINK | F_SEAL_GROW);
> +
> +	CHECK_MFD_READABLE(fd);
> +	CHECK_MFD_WRITEABLE(fd);
> +	CHECK_MFD_NON_SHRINKABLE(fd);
> +	CHECK_MFD_NON_GROWABLE(fd);
> +	CHECK_NON_GROWABLE_BY_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_MFD_HAS_SEALS(fd, 0);
> +
> +	fd2 = SAFE_DUP(fd);
> +	CHECK_MFD_HAS_SEALS(fd2, 0);
> +
> +	CHECK_MFD_ADD_SEALS(fd, F_SEAL_WRITE);
> +	CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE);
> +	CHECK_MFD_HAS_SEALS(fd2, F_SEAL_WRITE);
> +
> +	CHECK_MFD_ADD_SEALS(fd2, F_SEAL_SHRINK);
> +	CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
> +	CHECK_MFD_HAS_SEALS(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
> +
> +	CHECK_MFD_ADD_SEALS(fd, F_SEAL_SEAL);
> +	CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
> +	CHECK_MFD_HAS_SEALS(fd2, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
> +
> +	CHECK_MFD_FAIL_ADD_SEALS(fd, F_SEAL_GROW);
> +	CHECK_MFD_FAIL_ADD_SEALS(fd2, F_SEAL_GROW);
> +	CHECK_MFD_FAIL_ADD_SEALS(fd, F_SEAL_SEAL);
> +	CHECK_MFD_FAIL_ADD_SEALS(fd2, F_SEAL_SEAL);
> +
> +	SAFE_CLOSE(fd2);
> +
> +	CHECK_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_MFD_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_MFD_FAIL_ADD_SEALS(fd, F_SEAL_WRITE);
> +	CHECK_MFD_HAS_SEALS(fd, 0);
> +	CHECK_MFD_ADD_SEALS(fd, F_SEAL_SHRINK);
> +	CHECK_MFD_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_MFD_ADD_SEALS(fd, F_SEAL_WRITE);
> +	CHECK_MFD_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_MFD_HAS_SEALS(fd, 0);
> +
> +	fd2 = CHECK_MFD_OPEN(fd, O_RDWR, 0);
> +	CHECK_MFD_ADD_SEALS(fd, F_SEAL_WRITE);
> +	CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE);
> +	CHECK_MFD_HAS_SEALS(fd2, F_SEAL_WRITE);
> +
> +	CHECK_MFD_ADD_SEALS(fd2, F_SEAL_SHRINK);
> +	CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
> +	CHECK_MFD_HAS_SEALS(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
> +
> +	SAFE_CLOSE(fd);
> +	fd = CHECK_MFD_OPEN(fd2, O_RDONLY, 0);
> +
> +	CHECK_MFD_FAIL_ADD_SEALS(fd, F_SEAL_SEAL);
> +	CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
> +	CHECK_MFD_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},
> +};

What about adding an short test description here and priting it as a
TINFO message before we run particular test function something as:

static const struct tcase {
	int flags;
	void (*func)(int fd);
	const char *desc;
} tcases[] = {
	{MFD_ALLOW_SEALING, &test_basic, "Basic tests"},
	{0,                 &test_no_sealing_without_flag, "Disabled sealing"},

	{MFD_ALLOW_SEALING, &test_seal_write, "Write seal"},
	{MFD_ALLOW_SEALING, &test_seal_shrink, "Shring seal"},
	{MFD_ALLOW_SEALING, &test_seal_grow, "Grow seal"},
	{MFD_ALLOW_SEALING, &test_seal_resize, "Resize seal"},

	{MFD_ALLOW_SEALING, &test_share_dup, "Seals shared for dup"},
	{MFD_ALLOW_SEALING, &test_share_mmap, "Seals shared for mmap"},
	{MFD_ALLOW_SEALING, &test_share_open, "Seals shared for open"},
};

static void verify_memfd_create(unsigned int n)
{
	int fd;
	const struct tcase *tc;

	tc = &tcases[n];

	tst_res(TINFO, "%s", tc->desc);

	...
}

> +static void verify_memfd_create(unsigned int n)
> +{
> +	int fd;
> +	const struct tcase *tc;
> +
> +	tc = &tcases[n];
> +
> +	fd = CHECK_MFD_NEW(TCID, MFD_DEF_SIZE, tc->flags);
> +
> +	tc->func(fd);
> +
> +	SAFE_CLOSE(fd);
> +}
> +
> +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..71f4123
> --- /dev/null
> +++ b/testcases/kernel/syscalls/memfd_create/memfd_create_common.h
> @@ -0,0 +1,457 @@
> +/*
> + * 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
> +
> +static int sys_memfd_create(const char *name, unsigned int flags)
> +{
> +	return tst_syscall(__NR_memfd_create, name, flags);
> +}
> +
> +static void check_ftruncate(const char *filename, const int lineno,
> +		int fd, off_t length)
> +{
> +	safe_ftruncate(filename, lineno, fd, length);
> +
> +	tst_res_(filename, lineno, TPASS,
> +			"ftruncate(%d, %ld) succeeded", fd, length);
> +}
> +
> +static void check_ftruncate_fail(const char *filename, const int lineno,
> +		int fd, off_t length)
> +{
> +	if (ftruncate(fd, length) >= 0)
> +		tst_brk_(filename, lineno, TFAIL,
> +				"ftruncate(%d, %ld) succeeded unexpectedly",
> +				fd, length);

Here as well, no need to end the test with tst_brk_() (see below for
explanation).

> +	tst_res_(filename, lineno, TPASS | TERRNO,
> +			"ftruncate(%d, %ld) failed as expected", fd, length);
> +}
> +
> +#define CHECK_MFD_NEW(name, sz, flags) \
> +	check_mfd_new(__FILE__, __LINE__, name, (sz), (flags))
> +
> +static int check_mfd_new(const char *filename, const int lineno,
> +		const char *name, loff_t sz, int flags)
> +{
> +	int fd;
> +
> +	fd = sys_memfd_create(name, flags);
> +	if (fd < 0)
> +		tst_brk_(filename, lineno, TBROK | TERRNO,
> +				"memfd_create(%s, %d) failed", name, flags);
> +	tst_res_(filename, lineno, TPASS, "memfd_create(%s, %d) succeeded",
> +			name, flags);
> +
> +	check_ftruncate(filename, lineno, fd, sz);
> +
> +	return fd;
> +}
> +
> +static int check_fallocate(const char *filename, const int lineno,
> +		int fd, int mode, off_t offset, off_t len)
> +{
> +	int r;
> +
> +	r = fallocate(fd, mode, offset, len);
> +	if (r < 0)
> +		tst_brk_(filename, lineno, TFAIL | TERRNO,
> +				"fallocate(%d, %d, %ld, %ld) failed",
> +				fd, mode, offset, len);
> +
> +	tst_res_(filename, lineno, TPASS,
> +			"fallocate(%d, %d, %ld, %ld) succeeded",
> +			fd, mode, offset, len);
> +
> +	return r;
> +}
> +
> +static int check_fallocate_fail(const char *filename, const int lineno,
> +		int fd, int mode, off_t offset, off_t len)
> +{
> +	int r;
> +
> +	r = fallocate(fd, mode, offset, len);
> +	if (r >= 0)
> +		tst_brk_(filename, lineno, TFAIL,
> +			"fallocate(%d, %d, %ld, %ld) succeeded unexpectedly",
> +			fd, mode, offset, len);

Here as well.

> +	tst_res_(filename, lineno, TPASS | TERRNO,
> +			"fallocate(%d, %d, %ld, %ld) failed as expected",
> +			fd, mode, offset, len);
> +
> +	return r;
> +}
> +
> +#define ASSERT_HAVE_MEMFD_CREATE() \
> +	assert_have_memfd_create(__FILE__, __LINE__)
> +
> +void assert_have_memfd_create(const char *filename, const int lineno)
> +{
> +	int flags;
> +
> +	TEST(sys_memfd_create("dummy_call", 0));
> +	if (TEST_RETURN < 0) {
> +		flags = ((TERRNO == -ENOSYS ||
> +			TERRNO == -EINVAL) ? TCONF : TBROK) | TERRNO;

The errno flags are always positive in userspace, also TERRNO is bitflag
not the variable the errno value is stored to. Also ENOSYS is handled in
tst_syscall() already. So the check here should be:

	if (TEST_ERRNO == EINVAL) {
		tst_brk_(filename, lineno, TCONF | TTERRNO,
			 "memfd_create() not implemented");
	}

	tst_brk(filename, lineno, TBROK | TTERRNO,
	        "memfd_create() failed");

> +		tst_brk_(filename, lineno, flags, "memfd_create() failed");
> +	}
> +
> +	SAFE_CLOSE(TEST_RETURN);
> +}
> +
> +
> +#define CHECK_MFD_FAIL_NEW(name, flags) \
> +	do { \
> +		int fd; \
> +		fd = sys_memfd_create((name), (flags)); \
> +		if (fd >= 0) { \
> +			safe_close(__FILE__, __LINE__, NULL, fd); \
> +			tst_brk(TFAIL, \
> +				"memfd_create(%s, %d) succeeded unexpectedly",\
> +				(name), (flags)); \
> +		} \
> +		tst_res_(__FILE__, __LINE__, TPASS | TERRNO, \
> +			"memfd_create(%s, %d) failed as expected", \
> +			(name), (flags)) \
> +	} while (0)
> +
> +#define CHECK_MMAP_FAIL(addr, length, prot, flags, fd, offset) \
> +	check_mmap_fail(__FILE__, __LINE__, (addr), (length), (prot), \
> +			(flags), (fd), (offset))
> +
> +void check_mmap_fail(const char *file, const int lineno, void *addr,
> +		size_t length, int prot, int flags, int fd, off_t offset)
> +{
> +	if (mmap(addr, length, prot, flags, fd, offset) != MAP_FAILED) {
> +		tst_brk_(file, lineno, TFAIL,
> +			"mmap(%p, %zu, %i, %i, %i, %zi) succeeded unexpectedly",
> +			addr, length, prot, flags, fd, offset);

No reason to break the test here as well, we can just do tst_res_()
followed by return here.

> +	}
> +
> +	tst_res_(file, lineno, TPASS | TERRNO,
> +			"mmap(%p, %zu, %i, %i, %i, %zi) failed as expected",
> +			addr, length, prot, flags, fd, offset);
> +}
> +
> +#define CHECK_MMAP(addr, length, prot, flags, fd, offset) \
> +	check_mmap(__FILE__, __LINE__, (addr), (length), (prot), \
> +			(flags), (fd), (offset))
> +
> +void *check_mmap(const char *file, const int lineno, void *addr,
> +		size_t length, int prot, int flags, int fd, off_t offset)
> +{
> +	void *p;
> +
> +	p = safe_mmap(file, lineno, addr, length, prot, flags, fd, offset);
> +
> +	tst_res_(file, lineno, TPASS,
> +			"mmap(%p, %zu, %i, %i, %i, %zi) succeeded",
> +			addr, length, prot, flags, fd, offset);
> +
> +	return p;
> +}
> +
> +#define CHECK_MUNMAP(p, length) \
> +	check_munmap(__FILE__, __LINE__, (p), (length))
> +
> +void check_munmap(const char *file, const int lineno, void *p, size_t length)
> +{
> +	safe_munmap(file, lineno, NULL, p, length);
> +	tst_res_(file, lineno, TPASS, "munmap(%p, %ld) succeeded",
> +			p, length);
> +}
> +
> +void check_mprotect(const char *file, const int lineno, void *addr,
> +		size_t length, int prot)
> +{
> +	if (mprotect(addr, length, prot) < 0)
> +		tst_brk_(file, lineno, TFAIL | TERRNO,
> +			"mprotect(%p, %ld, %d) failed", addr, length, prot);
> +
> +	tst_res_(file, lineno, TPASS,
> +			"mprotect(%p, %ld, %d) succeeded", addr, length, prot);
> +}
> +
> +#define CHECK_MFD_GET_SEALS(fd) \
> +	({int r = SAFE_FCNTL((fd), F_GET_SEALS); \
> +	 tst_res(TPASS, "fcntl(%d, F_GET_SEALS) succeeded", (fd)); r; })
> +
> +#define CHECK_MFD_HAS_SEALS(fd, seals) \
> +	do { \
> +		if (CHECK_MFD_GET_SEALS((fd)) != (seals)) \
> +		tst_brk(TFAIL, "fd %d doesn't have expected seals", (fd)); \

Wrong indentation here as well. Also can we print the seals value in
both of these messages.

Also I would have just called SAFE_FCNTL() here directly instead of
adding another level of indirection with CHECK_MFD_GET_SEALS(). One
TPASS message for CHECK_MFD_HAS_SEALS() in case that we happened to
get the seals and the value is correct is enough.

> +		tst_res(TPASS, "fd %d has expected seals", (fd)); \
> +	} while (0)
> +
> +#define CHECK_MFD_ADD_SEALS(fd, seals) \
> +	({int r = SAFE_FCNTL((fd), F_ADD_SEALS, (seals)); \
> +	 tst_res(TPASS, "fcntl(%d, F_ADD_SEALS, %d) succeeded", \
> +		 (fd), (seals)); r; })
> +
> +#define CHECK_MFD_FAIL_ADD_SEALS(fd, seals) \
> +	do { \
> +		if (fcntl((fd), F_ADD_SEALS, (seals)) >= 0) \
> +		tst_brk(TFAIL, \
> +			"fcntl(%d, F_ADD_SEALS) succeeded unexpectedly", \
> +			(fd)); \

This indentation is wrong and confusing.

The inner tst_brk() should be indented to the right and ideally the
multi-line fucntion call should be enclosed in curly braces as LKML
coding style prefers mutliline statements in conditions or loops
enclosed int them.

Also the code would be more readable as a function...

> +		tst_res(TPASS | TERRNO, \
> +			"fcntl(%d, F_ADD_SEALS, %d) failed as expected", \
> +				(fd), (seals)); \
> +	} while (0)

> +#define CHECK_MFD_SIZE(fd, size) \
> +	check_mfd_size(__FILE__, __LINE__, (fd), (size))
> +
> +static void check_mfd_size(const char *filename, const int lineno,
> +		int fd, size_t size)
> +{
> +	struct stat st;
> +
> +	safe_fstat(filename, lineno, fd, &st);
> +
> +	if (st.st_size != (long)size)
> +		tst_brk_(filename, lineno, TFAIL,
> +				"fstat(%d, &st): unexpected file size", fd);
> +
> +	tst_res_(filename, lineno, TPASS,
> +			"fstat(%d, &st): file size is correct", fd);
> +}
> +
> +#define CHECK_MFD_OPEN(fd, flags, mode) \
> +	check_mfd_open(__FILE__, __LINE__, (fd), (flags), (mode))
> +
> +static int check_mfd_open(const char *filename, const int lineno, int fd,
> +		int flags, mode_t mode)
> +{
> +	int r;
> +	char buf[512];
> +
> +	sprintf(buf, "/proc/self/fd/%d", fd);
> +
> +	r = safe_open(filename, lineno, NULL, buf, flags, mode);
> +	tst_res_(filename, lineno, TPASS, "open(%s, %d, %d) succeeded",
> +			buf, flags, mode);
> +
> +	return r;
> +}
> +
> +#define CHECK_MFD_FAIL_OPEN(fd, flags, mode) \
> +	do { \
> +		char buf[512]; \
> +		sprintf(buf, "/proc/self/fd/%d", (fd)); \
> +		if (open(buf, (flags), (mode)) >= 0) \
> +		tst_brk(TFAIL, "open(%s, %d, %d) succeeded unexpectedly",\
> +				buf, (flags), (mode)); \
> +		tst_res(TPASS | TERRNO, "open(%s, %d, %d) failed as expected",\
> +				buf, (flags), (mode));\

Again utterly confusing indentation. Also there is no reason not to
continue the test if the open() haven't failed (since this unlike failed
attempt to seal the memfd this failure would not cause subsequent test
fail).

Hence we can do something as:

	fd = open(...)
	if (fd > 0) {
		close(fd);
		tst_res(TFAIL ...);
	} else {
		tst_res(TPASS ...);
	}

> +	} while (0)
> +
> +#define CHECK_MFD_READABLE(fd) \
> +	check_mfd_readable(__FILE__, __LINE__, (fd))
> +
> +static void check_mfd_readable(const char *filename, const int lineno, int fd)
> +{
> +	char buf[16];
> +	void *p;
> +
> +	safe_read(filename, lineno, NULL, 1, fd, buf, sizeof(buf));
> +	tst_res_(filename, lineno, TPASS, "read(%d, %s, %ld) succeeded",
> +			fd, buf, sizeof(buf));
> +
> +	/* verify PROT_READ *is* allowed */
> +	p = check_mmap(filename, lineno, NULL, MFD_DEF_SIZE,
> +			PROT_READ, MAP_PRIVATE, fd, 0);
> +
> +	check_munmap(filename, lineno, p, MFD_DEF_SIZE);
> +
> +	/* verify MAP_PRIVATE is *always* allowed (even writable) */
> +	p = check_mmap(filename, lineno, NULL, MFD_DEF_SIZE,
> +			PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
> +
> +	check_munmap(filename, lineno, p, MFD_DEF_SIZE);
> +}
> +
> +#define CHECK_MFD_WRITEABLE(fd) \
> +	check_mfd_writeable(__FILE__, __LINE__, (fd))
> +
> +static void check_mfd_writeable(const char *filename,
> +		const int lineno, int fd)
> +{
> +	void *p;
> +
> +	/* verify write() succeeds */
> +	safe_write(filename, lineno, NULL, 1, fd, "\0\0\0\0", 4);
> +	tst_res_(filename, lineno, TPASS, "write(%d, %p, %d) succeeded",
> +			fd, "\0\0\0\0", 4);
> +
> +	/* verify PROT_READ | PROT_WRITE is allowed */
> +	p = check_mmap(filename, lineno, NULL, MFD_DEF_SIZE,
> +			PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
> +
> +	*(char *)p = 0;
> +	check_munmap(filename, lineno, p, MFD_DEF_SIZE);
> +
> +	/* verify PROT_WRITE is allowed */
> +	p = check_mmap(filename, lineno, NULL, MFD_DEF_SIZE,
> +			PROT_WRITE, MAP_SHARED, fd, 0);
> +
> +	*(char *)p = 0;
> +	check_munmap(filename, lineno, p, MFD_DEF_SIZE);
> +
> +	/* verify PROT_READ with MAP_SHARED is allowed and a following
> +	 * mprotect(PROT_WRITE) allows writing
> +	 */
> +	p = check_mmap(filename, lineno, NULL, MFD_DEF_SIZE,
> +			PROT_READ, MAP_SHARED, fd, 0);
> +
> +	check_mprotect(filename, lineno, p, MFD_DEF_SIZE,
> +			PROT_READ | PROT_WRITE);
> +
> +	*(char *)p = 0;
> +	check_munmap(filename, lineno, p, MFD_DEF_SIZE);
> +
> +	/* verify PUNCH_HOLE works */
> +	check_fallocate(filename, lineno, fd,
> +			FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
> +			0, MFD_DEF_SIZE);
> +}
> +
> +#define CHECK_MFD_NON_WRITEABLE(fd) \
> +	check_mfd_non_writeable(__FILE__, __LINE__, (fd))
> +
> +static void check_mfd_non_writeable(const char *filename,
> +		const int lineno, int fd)
> +{
> +	ssize_t l;
> +	void *p;
> +
> +	/* verify write() fails */
> +	l = write(fd, "data", 4);
> +	if (l != -EPERM)
> +		tst_brk(TFAIL | TERRNO, "write() didn't fail as expected");

This is plain wrong. The write() function returns -1 and errno is set to
EPERM and this code works only by a chance since EPERM == 1.

> +	/* verify PROT_READ | PROT_WRITE is not allowed */
> +	check_mmap_fail(filename, lineno, NULL, MFD_DEF_SIZE,
> +			PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
> +
> +	/* verify PROT_WRITE is not allowed */
> +	check_mmap_fail(filename, lineno, NULL, MFD_DEF_SIZE,
> +			PROT_WRITE, MAP_SHARED, fd, 0);
> +
> +	/* 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) {
> +		if (mprotect(p, MFD_DEF_SIZE, PROT_READ | PROT_WRITE) >= 0)
> +			tst_brk(TFAIL | TERRNO,
> +				"mmap()+mprotect() succeeded unexpectedly");
> +	}
> +
> +	/* verify PUNCH_HOLE fails */
> +	check_fallocate_fail(filename, lineno, fd,
> +		FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, MFD_DEF_SIZE);
> +}
> +
> +#define CHECK_MFD_SHRINKABLE(fd) \
> +	check_mfd_shrinkable(__FILE__, __LINE__, (fd))
> +
> +static void check_mfd_shrinkable(const char *filename,
> +				const int lineno, int fd)
> +{
> +	int fd2;
> +
> +	check_ftruncate(filename, lineno, fd, MFD_DEF_SIZE / 2);
> +	check_mfd_size(filename, lineno, fd, MFD_DEF_SIZE / 2);
> +
> +	fd2 = check_mfd_open(filename, lineno, fd,
> +			O_RDWR | O_CREAT | O_TRUNC, 0600);
> +	safe_close(filename, lineno, NULL, fd2);
> +
> +	check_mfd_size(filename, lineno, fd, 0);
> +}
> +
> +#define CHECK_MFD_NON_SHRINKABLE(fd) \
> +	do { \
> +		check_ftruncate_fail(__FILE__, __LINE__, (fd), \
> +				MFD_DEF_SIZE / 2); \
> +		CHECK_MFD_FAIL_OPEN((fd), (O_RDWR | O_CREAT | O_TRUNC), 0600);\
> +	} while (0)
> +
> +#define CHECK_MFD_GROWABLE(fd) \
> +	check_mfd_growable(__FILE__, __LINE__, (fd))
> +
> +static void check_mfd_growable(const char *filename, const int lineno, int fd)
> +{
> +	check_ftruncate(filename, lineno, fd, MFD_DEF_SIZE * 2);
> +	check_mfd_size(filename, lineno, fd, MFD_DEF_SIZE * 2);
> +
> +	check_fallocate(filename, lineno, fd, 0, 0, MFD_DEF_SIZE * 4);
> +	check_mfd_size(filename, lineno, fd, MFD_DEF_SIZE * 4);
> +}
> +
> +#define CHECK_MFD_NON_GROWABLE(fd) \
> +	do { \
> +		check_ftruncate_fail(__FILE__, __LINE__, fd, \
> +				MFD_DEF_SIZE * 2); \
> +		check_fallocate_fail(__FILE__, __LINE__, fd, \
> +				0, 0, MFD_DEF_SIZE * 4); \
> +	} while (0)
> +
> +#define CHECK_GROWABLE_BY_WRITE(fd) \
> +	do {\
> +		char buf[MFD_DEF_SIZE * 8]; \
> +		if (pwrite((fd), buf, sizeof(buf), 0) != sizeof(buf)) \
> +		tst_brk(TFAIL | TERRNO, "pwrite(%d, %s, %ld, %d) failed", \
> +				(fd), buf, sizeof(buf), 0); \

Here again broken indentation and no need for breaking the test.

> +		tst_res(TPASS, "pwrite(%d, %s, %ld, %d) succeeded", \
> +				(fd), buf, sizeof(buf), 0); \
> +		check_mfd_size(__FILE__, __LINE__, (fd), MFD_DEF_SIZE * 8); \
> +	} while (0)
> +
> +#define CHECK_NON_GROWABLE_BY_WRITE(fd) \
> +	do { \
> +		char buf[MFD_DEF_SIZE * 8]; \
> +		if (pwrite((fd), buf, sizeof(buf), 0) == sizeof(buf)) \
> +		tst_brk(TFAIL, \
> +			"pwrite(%d, %s, %ld, %d) didn't fail as expected", \
> +			(fd), buf, sizeof(buf), 0); \

Here as well and also missign TPASS message.

> +	} while (0)
> +
> +#endif

And lastly but not least to the warnings produced by the inclusion of
this file in the second test. There are couple of ways to fix it.

The easiest, but not cleanest solution would be dropping the static
keywords from the function definitions.

And much cleaner way would be implementing these the way safe macros are
done. I.e. moving the actual functions into memfd_common.c source file
and leaving only the definitions in the header. You would have to add a
few lines into the Makefile, see testcases/kernel/fs/ftest/Makefile for
example how to do that.

-- 
Cyril Hrubis
chrubis@suse.cz

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

end of thread, other threads:[~2017-03-22 10:19 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-15 16:35 [LTP] [PATCH v4 0/6] Added memfd_create() testsuite Jakub Racek
2017-03-15 16:35 ` [LTP] [PATCH v4 1/6] Added syscall numbers for memfd_create Jakub Racek
2017-03-15 16:35 ` [LTP] [PATCH v4 2/6] Added memfd_create() lapi flags Jakub Racek
2017-03-15 16:35 ` [LTP] [PATCH v4 3/6] Added fcntl() " Jakub Racek
2017-03-15 16:35 ` [LTP] [PATCH v4 4/6] move fallocate.h to lapi Jakub Racek
2017-03-15 16:35 ` [LTP] [PATCH v4 5/6] syscalls: added memfd_create dir and memfd_create/memfd_create01.c Jakub Racek
2017-03-21 15:27   ` Cyril Hrubis
2017-03-21 17:46     ` Jakub =?unknown-8bit?q?Ra=C4=8Dek?=
2017-03-22 10:19   ` Cyril Hrubis
2017-03-15 16:35 ` [LTP] [PATCH v4 6/6] syscalls/memfd_create02.c: added new test Jakub Racek

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.