summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Yuan <me@yhndnzj.com>2023-05-16 22:00:57 +0800
committerGitHub <noreply@github.com>2023-05-16 22:00:57 +0800
commit329f4b06f5124a8db042e8bd42fbc3265744aaa6 (patch)
treeebf0bd399aebe561ed2998920150d81250e2996b /src
parent0313c41068a362178190eac81f64b60223bb4c0c (diff)
parent3418ca21ed4dc08a26bed31d629e3fd4f9a2e191 (diff)
downloadsystemd-329f4b06f5124a8db042e8bd42fbc3265744aaa6.tar.gz
Merge pull request #27659 from yuwata/memfd-seal
memfd-util: handle F_SEAL_EXEC flag
Diffstat (limited to 'src')
-rw-r--r--src/basic/memfd-util.c11
-rw-r--r--src/basic/missing_fcntl.h8
-rw-r--r--src/test/meson.build1
-rw-r--r--src/test/test-memfd-util.c30
4 files changed, 48 insertions, 2 deletions
diff --git a/src/basic/memfd-util.c b/src/basic/memfd-util.c
index 285abd41d3..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) {
@@ -106,7 +112,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) {
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
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 <unistd.h>
+
+#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);