syscalls/memfd_create: test memfd flags separately
PATCH 1/1 syscalls/memfd_create: test memfd flags separately
This patch fixes the test on some kernels where memfd_create doesn't have have sealing support. Calls to memfd_create are done so that we know what flags are available. Depending on that, some tests are skipped instead of incorrectly reporting breakage.
--- .../kernel/syscalls/memfd_create/memfd_create01.c | 16 +++++++- .../kernel/syscalls/memfd_create/memfd_create02.c | 25 +++++++----- .../syscalls/memfd_create/memfd_create_common.c | 44 +++++++++++++++++++--- .../syscalls/memfd_create/memfd_create_common.h | 12 ++++-- 4 files changed, 78 insertions(+), 19 deletions(-)
testcases/kernel/syscalls/memfd_create/memfd_create01.c +15 -1
@@ -22,6 +22,7 @@#define _GNU_SOURCE +#include <errno.h> #include "tst_test.h" #include "memfd_create_common.h"
@@ -259,7 +260,20 @@ static void verify_memfd_create(unsigned int n)static void setup (void ) { -ASSERT_HAVE_MEMFD_CREATE (); + +int available_flags; + +/* +* For now, all tests in this file require MFD_ALLOW_SEALING flag +* to be implemented, even though that flag isn't always set when +* memfd is created. So don't check anything else and TCONF right away +* is this flag is missing. +*/ + available_flags =GET_MFD_ALL_AVAILABLE_FLAGS (); +if ((available_flags &MFD_ALLOW_SEALING ) !=MFD_ALLOW_SEALING ) { +tst_brk (TCONF |TTERRNO , +"memfd_create(%u) not implemented" ,MFD_ALLOW_SEALING ); + } }static struct tst_test test = {
testcases/kernel/syscalls/memfd_create/memfd_create02.c +16 -9
@@ -31,6 +31,8 @@static char buf[2048 ];static char term_buf[2048 ]; +static int available_flags; + static const struct tcase { char *descr; char *memfd_name;
@@ -62,7 +64,8 @@ static const struct tcase {static void setup (void ) { -ASSERT_HAVE_MEMFD_CREATE (); + + available_flags =GET_MFD_ALL_AVAILABLE_FLAGS ();memset (buf,0xff ,sizeof (buf));
@@ -76,14 +79,18 @@ static void verify_memfd_create_errno(unsigned int n) 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 ); +if ((available_flags & tc->flags) == tc->flags) { +TEST (sys_memfd_create (tc->memfd_name, tc->flags)); +if (tc->memfd_create_exp_err !=TEST_ERRNO ) +tst_brk (TFAIL ,"test '%s'" , tc->descr); +else +tst_res (TPASS ,"test '%s'" , tc->descr); + +if (TEST_RETURN >0 ) +SAFE_CLOSE (TEST_RETURN ); + }else +tst_res (TCONF ,"test '%s' skipped, flag not implemented" , + tc->descr); }static struct tst_test test = {
testcases/kernel/syscalls/memfd_create/memfd_create_common.c +38 -6
58 lines not on this page · raw message
testcases/kernel/syscalls/memfd_create/memfd_create_common.h +9 -3
@@ -22,8 +22,12 @@#define MFD_DEF_SIZE 8192 -#define ASSERT_HAVE_MEMFD_CREATE () \ - assert_have_memfd_create(__FILE__, __LINE__) +#define MFD_AVAILABLE 0 +#define MFD_FAILED 1 +#define MFD_FLAG_NOT_IMPLEMENTED 2 + +#define GET_MFD_ALL_AVAILABLE_FLAGS () \ + get_mfd_all_available_flags(__FILE__, __LINE__)#define CHECK_MFD_NEW (name, sz, flags) \ check_mfd_new(__FILE__, __LINE__, (name), (sz), (flags))
@@ -89,7 +93,9 @@#define CHECK_MFD_NON_GROWABLE_BY_WRITE (fd) \ check_mfd_non_growable_by_write(__FILE__, __LINE__, (fd)) -void assert_have_memfd_create (const char *filename,const int lineno); +int check_mfd_available_with_flags (unsigned int flags); +int get_mfd_all_available_flags (const char *filename,const int lineno); +int sys_memfd_create (const char *name,unsigned int flags); int check_fallocate(const char *filename, const int lineno, int fd,
Signature · 1 line
1.8.3.1
PATCH 1/1 syscalls/memfd_create: test memfd flags separately
Hi!
Quoted 84 lines
This patch fixes the test on some kernels where
memfd_createdoesn't have have sealing support. Calls tomemfd_createare done so that we know what flags are available. Depending on that, some tests are skipped instead of incorrectly reporting breakage.Signed-off-by Jakub Racek <[email protected]>--- .../kernel/syscalls/memfd_create/memfd_create01.c | 16 +++++++- .../kernel/syscalls/memfd_create/memfd_create02.c | 25 +++++++----- .../syscalls/memfd_create/memfd_create_common.c | 44 +++++++++++++++++++--- .../syscalls/memfd_create/memfd_create_common.h | 12 ++++-- 4 files changed, 78 insertions(+), 19 deletions(-)testcases/kernel/syscalls/memfd_create/memfd_create01.c +15
-1@@ -22,6 +22,7 @@#define _GNU_SOURCE +#include <errno.h> #include "tst_test.h" #include "memfd_create_common.h" @@ -259,7 +260,20 @@ static void verify_memfd_create(unsigned int n)static void setup (void ) { -ASSERT_HAVE_MEMFD_CREATE (); + +int available_flags; + +/* +* For now, all tests in this file require MFD_ALLOW_SEALING flag +* to be implemented, even though that flag isn't always set when +* memfd is created. So don't check anything else and TCONF right away +* is this flag is missing. +*/ + available_flags =GET_MFD_ALL_AVAILABLE_FLAGS (); +if ((available_flags &MFD_ALLOW_SEALING ) !=MFD_ALLOW_SEALING ) { +tst_brk (TCONF |TTERRNO , +"memfd_create(%u) not implemented" ,MFD_ALLOW_SEALING ); + } }static struct tst_test test = {testcases/kernel/syscalls/memfd_create/memfd_create02.c +6
-9@@ -31,6 +31,8 @@static char buf[2048 ];static char term_buf[2048 ]; +static int available_flags; + static const struct tcase { char *descr; char *memfd_name;@@ -62,7 +64,8 @@ static const struct tcase {static void setup (void ) { -ASSERT_HAVE_MEMFD_CREATE (); + + available_flags =GET_MFD_ALL_AVAILABLE_FLAGS ();memset (buf,0xff ,sizeof (buf));@@ -76,14 +79,18 @@ static void verify_memfd_create_errno(unsigned int n) 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 ); +if ((available_flags & tc->flags) == tc->flags) { +TEST (sys_memfd_create (tc->memfd_name, tc->flags));
testcases/kernel/syscalls/memfd_create/memfd_create02.c static void verify_memfd_create_errno(unsigned int n) · line 93
Quoted 10 lines
testcases/kernel/syscalls/memfd_create/memfd_create02.c +10
-0+if (tc->memfd_create_exp_err !=TEST_ERRNO ) +tst_brk (TFAIL ,"test '%s'" , tc->descr); +else +tst_res (TPASS ,"test '%s'" , tc->descr); + +if (TEST_RETURN >0 ) +SAFE_CLOSE (TEST_RETURN ); + }else +tst_res (TCONF ,"test '%s' skipped, flag not implemented" , + tc->descr);
It would be a bit cleaner to check for the flags first and return from the function if flag is not available, i.e.
if ((available_flags & tc->flags) != tc->flags) {
tst_res(TCONF, ...);
return;
}
TEST(sys_memfd_create(...));
...Quoted 31 lines
testcases/kernel/syscalls/memfd_create/memfd_create02.c +0
-0}static struct tst_test test = {testcases/kernel/syscalls/memfd_create/memfd_create_common.c +17
-2@@ -103,20 +103,52 @@ void check_ftruncate_fail(const char *filename, const int lineno, "ftruncate(%d, %ld) failed as expected", fd, length); } -void assert_have_memfd_create (const char *filename,const int lineno) +int get_mfd_all_available_flags (const char *filename,const int lineno) { -TEST (sys_memfd_create ("dummy_call" ,0 )); +unsigned int i; +int flag; +int flags2test[] = {0 ,MFD_CLOEXEC ,MFD_ALLOW_SEALING }; +int flags_available =0 ; +int any_available =0 ; + +for (i =0 ; i <ARRAY_SIZE (flags2test); i++) { + flag = flags2test[i]; + +TEST (check_mfd_available_with_flags (flag)); +if (TEST_RETURN ==MFD_FLAG_NOT_IMPLEMENTED ) { +tst_res_ (filename, lineno,TINFO |TTERRNO , +"memfd_create(%u) not implemented" , flag); + }else if (TEST_RETURN ==MFD_FAILED ) { +tst_res_ (filename, lineno,TINFO |TTERRNO , +"memfd_create(%u) failed" , flag);
testcases/kernel/syscalls/memfd_create/memfd_create_common.c void check_ftruncate_fail(const char *filename, const int lineno, · line 133
Quoted 10 lines
testcases/kernel/syscalls/memfd_create/memfd_create_common.c +10
-0+ }else { + flags_available |= flag; + any_available =1 ; + } + } + +if (!any_available) { +tst_brk_ (filename, lineno,TCONF , +"memfd_create() not implemented at all" ); + }
Hmm, I wonder if there could be a situation where memfd_create() with flags = 0 will fail but memfd_creat() with non-zero flags will not. I doubt so but as the code is that will create a situaion where tests with flags = 0 will fail as well.
So what about checking for flags=0 first, doing tst_brk(TCONF, ...) if that is not working, then loop over the MFD_CLOEXEC and MFD_ALLOW_SEALING flags?
Quoted 6 lines
testcases/kernel/syscalls/memfd_create/memfd_create_common.c +6
-0+return flags_available; +} + +int check_mfd_available_with_flags (unsigned int flags) +{ +TEST (sys_memfd_create ("dummy_call" , flags));
testcases/kernel/syscalls/memfd_create/memfd_create_common.c void check_ftruncate_fail(const char *filename, const int lineno, · line 146
Quoted 10 lines
testcases/kernel/syscalls/memfd_create/memfd_create_common.c +2
-4if (TEST_RETURN <0 ) {if (TEST_ERRNO ==EINVAL ) { -tst_brk_ (filename, lineno,TCONF |TTERRNO , -"memfd_create() not implemented" ); +return MFD_FLAG_NOT_IMPLEMENTED ; } -tst_brk_ (filename, lineno,TBROK |TTERRNO , -"memfd_create() failed" ); +return MFD_FAILED ;
I would argue that if the mfd_create() has failed unexpectedly here the right thing to do is tst_brk(TBROK | TTERRNO, ...), there is no point in continuing the test if the syscall is failing for unknown reason, in that case the best course of action is to die quickly with a good description of the problem. Which also means that there is no point in returning anything else than 0 and 1 in this function, just return 0 if flags are not available and 1 if they are.
Quoted 44 lines
testcases/kernel/syscalls/memfd_create/memfd_create_common.c +2
-0}SAFE_CLOSE (TEST_RETURN ); + +return MFD_AVAILABLE ; } int check_mfd_new(const char *filename, const int lineno,testcases/kernel/syscalls/memfd_create/memfd_create_common.h +9
-3@@ -22,8 +22,12 @@#define MFD_DEF_SIZE 8192 -#define ASSERT_HAVE_MEMFD_CREATE () \ - assert_have_memfd_create(__FILE__, __LINE__) +#define MFD_AVAILABLE 0 +#define MFD_FAILED 1 +#define MFD_FLAG_NOT_IMPLEMENTED 2 + +#define GET_MFD_ALL_AVAILABLE_FLAGS () \ + get_mfd_all_available_flags(__FILE__, __LINE__)#define CHECK_MFD_NEW (name, sz, flags) \ check_mfd_new(__FILE__, __LINE__, (name), (sz), (flags))@@ -89,7 +93,9 @@#define CHECK_MFD_NON_GROWABLE_BY_WRITE (fd) \ check_mfd_non_growable_by_write(__FILE__, __LINE__, (fd)) -void assert_have_memfd_create (const char *filename,const int lineno); +int check_mfd_available_with_flags (unsigned int flags); +int get_mfd_all_available_flags (const char *filename,const int lineno); +int sys_memfd_create (const char *name,unsigned int flags); int check_fallocate(const char *filename, const int lineno, int fd,Signature · 5 lines
1.8.3.1 -- Mailing list info: https://lists.linux.it/listinfo/ltp
Signature · 2 lines
Cyril Hrubis [email protected]
PATCH 1/1 syscalls/memfd_create: test memfd flags separately
Hi,
Quoted 100 lines · Cyril Hrubis
Hi!
Quoted 84 lines
This patch fixes the test on some kernels where
memfd_createdoesn't have have sealing support. Calls tomemfd_createare done so that we know what flags are available. Depending on that, some tests are skipped instead of incorrectly reporting breakage.Signed-off-by Jakub Racek <[email protected]>--- .../kernel/syscalls/memfd_create/memfd_create01.c | 16 +++++++- .../kernel/syscalls/memfd_create/memfd_create02.c | 25 +++++++----- .../syscalls/memfd_create/memfd_create_common.c | 44 +++++++++++++++++++--- .../syscalls/memfd_create/memfd_create_common.h | 12 ++++-- 4 files changed, 78 insertions(+), 19 deletions(-)testcases/kernel/syscalls/memfd_create/memfd_create01.c +15
-1@@ -22,6 +22,7 @@#define _GNU_SOURCE +#include <errno.h> #include "tst_test.h" #include "memfd_create_common.h" @@ -259,7 +260,20 @@ static void verify_memfd_create(unsigned int n)static void setup (void ) { -ASSERT_HAVE_MEMFD_CREATE (); + +int available_flags; + +/* +* For now, all tests in this file require MFD_ALLOW_SEALING flag +* to be implemented, even though that flag isn't always set when +* memfd is created. So don't check anything else and TCONF right away +* is this flag is missing. +*/ + available_flags =GET_MFD_ALL_AVAILABLE_FLAGS (); +if ((available_flags &MFD_ALLOW_SEALING ) !=MFD_ALLOW_SEALING ) { +tst_brk (TCONF |TTERRNO , +"memfd_create(%u) not implemented" ,MFD_ALLOW_SEALING ); + } }static struct tst_test test = {testcases/kernel/syscalls/memfd_create/memfd_create02.c +6
-9@@ -31,6 +31,8 @@static char buf[2048 ];static char term_buf[2048 ]; +static int available_flags; + static const struct tcase { char *descr; char *memfd_name;@@ -62,7 +64,8 @@ static const struct tcase {static void setup (void ) { -ASSERT_HAVE_MEMFD_CREATE (); + + available_flags =GET_MFD_ALL_AVAILABLE_FLAGS ();memset (buf,0xff ,sizeof (buf));@@ -76,14 +79,18 @@ static void verify_memfd_create_errno(unsigned int n) 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 ); +if ((available_flags & tc->flags) == tc->flags) { +TEST (sys_memfd_create (tc->memfd_name, tc->flags));testcases/kernel/syscalls/memfd_create/memfd_create02.c static void verify_memfd_create_errno(unsigned int n) · line 93
Quoted 10 lines
testcases/kernel/syscalls/memfd_create/memfd_create02.c +10
-0+if (tc->memfd_create_exp_err !=TEST_ERRNO ) +tst_brk (TFAIL ,"test '%s'" , tc->descr); +else +tst_res (TPASS ,"test '%s'" , tc->descr); + +if (TEST_RETURN >0 ) +SAFE_CLOSE (TEST_RETURN ); + }else +tst_res (TCONF ,"test '%s' skipped, flag not implemented" , + tc->descr);It would be a bit cleaner to check for the flags first and return from the function if flag is not available, i.e.
Quoted 10 lines
if ((available_flags & tc->flags) != tc->flags) { tst_res(TCONF, ...); return; } TEST(sys_memfd_create(...)); ...Quoted 2 lines
testcases/kernel/syscalls/memfd_create/memfd_create02.c +0
-0}
Good catch, this actually has to be changed even more than that since memfd_create02 tests how api responds to invalid flags.
That and all other suggestions are reflected in V2 I'm sending now.
Quoted 111 lines
Quoted 29 lines
testcases/kernel/syscalls/memfd_create/memfd_create02.c +0
-0static struct tst_test test = {testcases/kernel/syscalls/memfd_create/memfd_create_common.c +17
-2@@ -103,20 +103,52 @@ void check_ftruncate_fail(const char *filename, const int lineno, "ftruncate(%d, %ld) failed as expected", fd, length); } -void assert_have_memfd_create (const char *filename,const int lineno) +int get_mfd_all_available_flags (const char *filename,const int lineno) { -TEST (sys_memfd_create ("dummy_call" ,0 )); +unsigned int i; +int flag; +int flags2test[] = {0 ,MFD_CLOEXEC ,MFD_ALLOW_SEALING }; +int flags_available =0 ; +int any_available =0 ; + +for (i =0 ; i <ARRAY_SIZE (flags2test); i++) { + flag = flags2test[i]; + +TEST (check_mfd_available_with_flags (flag)); +if (TEST_RETURN ==MFD_FLAG_NOT_IMPLEMENTED ) { +tst_res_ (filename, lineno,TINFO |TTERRNO , +"memfd_create(%u) not implemented" , flag); + }else if (TEST_RETURN ==MFD_FAILED ) { +tst_res_ (filename, lineno,TINFO |TTERRNO , +"memfd_create(%u) failed" , flag);testcases/kernel/syscalls/memfd_create/memfd_create_common.c void check_ftruncate_fail(const char *filename, const int lineno, · line 133
Quoted 10 lines
testcases/kernel/syscalls/memfd_create/memfd_create_common.c +10
-0+ }else { + flags_available |= flag; + any_available =1 ; + } + } + +if (!any_available) { +tst_brk_ (filename, lineno,TCONF , +"memfd_create() not implemented at all" ); + }Hmm, I wonder if there could be a situation where
memfd_create()with flags = 0 will fail butmemfd_creat()with non-zero flags will not. I doubt so but as the code is that will create a situaion where tests with flags = 0 will fail as well.So what about checking for flags=0 first, doing
tst_brk(TCONF, ...)if that is not working, then loop over theMFD_CLOEXECandMFD_ALLOW_SEALINGflags?Quoted 6 lines
testcases/kernel/syscalls/memfd_create/memfd_create_common.c +6
-0+return flags_available; +} + +int check_mfd_available_with_flags (unsigned int flags) +{ +TEST (sys_memfd_create ("dummy_call" , flags));testcases/kernel/syscalls/memfd_create/memfd_create_common.c void check_ftruncate_fail(const char *filename, const int lineno, · line 146
Quoted 10 lines
testcases/kernel/syscalls/memfd_create/memfd_create_common.c +2
-4if (TEST_RETURN <0 ) {if (TEST_ERRNO ==EINVAL ) { -tst_brk_ (filename, lineno,TCONF |TTERRNO , -"memfd_create() not implemented" ); +return MFD_FLAG_NOT_IMPLEMENTED ; } -tst_brk_ (filename, lineno,TBROK |TTERRNO , -"memfd_create() failed" ); +return MFD_FAILED ;I would argue that if the
mfd_create()has failed unexpectedly here the right thing to do istst_brk(TBROK | TTERRNO, ...), there is no point in continuing the test if the syscall is failing for unknown reason, in that case the best course of action is to die quickly with a good description of the problem. Which also means that there is no point in returning anything else than 0 and 1 in this function, just return 0 if flags are not available and 1 if they are.Quoted 37 lines
testcases/kernel/syscalls/memfd_create/memfd_create_common.c +2
-0}SAFE_CLOSE (TEST_RETURN ); + +return MFD_AVAILABLE ; } int check_mfd_new(const char *filename, const int lineno,testcases/kernel/syscalls/memfd_create/memfd_create_common.h +9
-3@@ -22,8 +22,12 @@#define MFD_DEF_SIZE 8192 -#define ASSERT_HAVE_MEMFD_CREATE () \ - assert_have_memfd_create(__FILE__, __LINE__) +#define MFD_AVAILABLE 0 +#define MFD_FAILED 1 +#define MFD_FLAG_NOT_IMPLEMENTED 2 + +#define GET_MFD_ALL_AVAILABLE_FLAGS () \ + get_mfd_all_available_flags(__FILE__, __LINE__)#define CHECK_MFD_NEW (name, sz, flags) \ check_mfd_new(__FILE__, __LINE__, (name), (sz), (flags))@@ -89,7 +93,9 @@#define CHECK_MFD_NON_GROWABLE_BY_WRITE (fd) \ check_mfd_non_growable_by_write(__FILE__, __LINE__, (fd)) -void assert_have_memfd_create (const char *filename,const int lineno); +int check_mfd_available_with_flags (unsigned int flags); +int get_mfd_all_available_flags (const char *filename,const int lineno); +int sys_memfd_create (const char *name,unsigned int flags);
Quoted 8 lines
Quoted 7 lines
testcases/kernel/syscalls/memfd_create/memfd_create_common.h +0
-1int check_fallocate(const char *filename, const int lineno, int fd, --1.8.3.1
--
Mailing list info: https://lists.linux.it/listinfo/ltp
Thank you.
Signature · 2 lines
Regards,
Jakub