* [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 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 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 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 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
* [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 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
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.