From 8e3303333faabadfff1c48935e21f7fd6d1b832e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 16 May 2023 18:46:16 +0900 Subject: [PATCH 1/4] missing: add more F_SEAL_XYZ flags --- src/basic/missing_fcntl.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/basic/missing_fcntl.h b/src/basic/missing_fcntl.h index 79e95a8f6f..24b2dc3119 100644 --- a/src/basic/missing_fcntl.h +++ b/src/basic/missing_fcntl.h @@ -25,6 +25,14 @@ #define F_SEAL_WRITE 0x0008 /* prevent writes */ #endif +#ifndef F_SEAL_FUTURE_WRITE +#define F_SEAL_FUTURE_WRITE 0x0010 /* prevent future writes while mapped */ +#endif + +#ifndef F_SEAL_EXEC +#define F_SEAL_EXEC 0x0020 /* prevent chmod modifying exec bits */ +#endif + #ifndef F_OFD_GETLK #define F_OFD_GETLK 36 #define F_OFD_SETLK 37 From 17915ea5b3d11790a8bd1f09335aa10bdf3c2a96 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 16 May 2023 18:48:29 +0900 Subject: [PATCH 2/4] memfd-util: memfd may also have F_SEAL_EXEC flag Follow-up for c29715a8f77d96cd731b4a3083b3a852b3b61eb8. Fixes #27608. --- src/basic/memfd-util.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/basic/memfd-util.c b/src/basic/memfd-util.c index 285abd41d3..3e99ab0480 100644 --- a/src/basic/memfd-util.c +++ b/src/basic/memfd-util.c @@ -106,7 +106,8 @@ int memfd_get_sealed(int fd) { if (r < 0) return -errno; - return r == (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL); + /* We ignore F_SEAL_EXEC here to support older kernels. */ + return FLAGS_SET(r, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL); } int memfd_get_size(int fd, uint64_t *sz) { From 52e2672af21827102a3192bd5e9b75070bc72297 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 16 May 2023 18:50:39 +0900 Subject: [PATCH 3/4] memfd-util: set F_SEAL_EXEC flag if supported --- src/basic/memfd-util.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/basic/memfd-util.c b/src/basic/memfd-util.c index 3e99ab0480..8e6946642b 100644 --- a/src/basic/memfd-util.c +++ b/src/basic/memfd-util.c @@ -92,9 +92,15 @@ int memfd_map(int fd, uint64_t offset, size_t size, void **p) { } int memfd_set_sealed(int fd) { + int r; + assert(fd >= 0); - return RET_NERRNO(fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL)); + r = RET_NERRNO(fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_EXEC | F_SEAL_SEAL)); + if (r == -EINVAL) /* old kernel ? */ + r = RET_NERRNO(fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL)); + + return r; } int memfd_get_sealed(int fd) { From 3418ca21ed4dc08a26bed31d629e3fd4f9a2e191 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 16 May 2023 18:59:25 +0900 Subject: [PATCH 4/4] test: add basic test for memfd_set_sealed() and memfd_get_sealed() --- src/test/meson.build | 1 + src/test/test-memfd-util.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 src/test/test-memfd-util.c diff --git a/src/test/meson.build b/src/test/meson.build index 8e76df624d..7f8de2a2ce 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -112,6 +112,7 @@ simple_tests += files( 'test-log.c', 'test-logarithm.c', 'test-macro.c', + 'test-memfd-util.c', 'test-memory-util.c', 'test-mempool.c', 'test-mkdir.c', diff --git a/src/test/test-memfd-util.c b/src/test/test-memfd-util.c new file mode 100644 index 0000000000..f8e1b46075 --- /dev/null +++ b/src/test/test-memfd-util.c @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include + +#include "errno-util.h" +#include "fd-util.h" +#include "memfd-util.h" +#include "string-util.h" +#include "tests.h" + +TEST(memfd_get_sealed) { +#define TEST_TEXT "this is some random test text we are going to write to a memfd" + _cleanup_close_ int fd = -EBADF; + + fd = memfd_new("test-memfd-get-sealed"); + if (fd < 0) { + assert_se(ERRNO_IS_NOT_SUPPORTED(fd)); + return; + } + + assert_se(write(fd, TEST_TEXT, strlen(TEST_TEXT)) == strlen(TEST_TEXT)); + /* we'll leave the read offset at the end of the memfd, the fdopen_independent() descriptors should + * start at the beginning anyway */ + + assert_se(memfd_get_sealed(fd) == 0); + assert_se(memfd_set_sealed(fd) >= 0); + assert_se(memfd_get_sealed(fd) > 0); +} + +DEFINE_TEST_MAIN(LOG_DEBUG);