From: jeffxu@chromium.org
To: skhan@linuxfoundation.org, keescook@chromium.org
Cc: akpm@linux-foundation.org, dmitry.torokhov@gmail.com,
dverkamp@chromium.org, hughd@google.com, jeffxu@google.com,
jorgelo@chromium.org, linux-kernel@vger.kernel.org,
linux-kselftest@vger.kernel.org, linux-mm@kvack.org,
mnissler@chromium.org, jannh@google.com,
linux-hardening@vger.kernel.org, Jeff Xu <jeffxu@chromium.org>
Subject: [PATCH v3] selftests/memfd: add tests for MFD_NOEXEC_SEAL MFD_EXEC
Date: Fri, 2 Dec 2022 01:34:02 +0000 [thread overview]
Message-ID: <20221202013404.163143-5-jeffxu@google.com> (raw)
In-Reply-To: <20221202013404.163143-1-jeffxu@google.com>
From: Jeff Xu <jeffxu@chromium.org>
Tests to verify MFD_NOEXEC, MFD_EXEC and vm.memfd_noexec sysctl.
Co-developed-by: Daniel Verkamp <dverkamp@chromium.org>
Signed-off-by: Daniel Verkamp <dverkamp@chromium.org>
Signed-off-by: Jeff Xu <jeffxu@chromium.org>
---
tools/testing/selftests/memfd/fuse_test.c | 1 +
tools/testing/selftests/memfd/memfd_test.c | 161 ++++++++++++++++++++-
2 files changed, 157 insertions(+), 5 deletions(-)
diff --git a/tools/testing/selftests/memfd/fuse_test.c b/tools/testing/selftests/memfd/fuse_test.c
index be675002f918..93798c8c5d54 100644
--- a/tools/testing/selftests/memfd/fuse_test.c
+++ b/tools/testing/selftests/memfd/fuse_test.c
@@ -22,6 +22,7 @@
#include <linux/falloc.h>
#include <fcntl.h>
#include <linux/memfd.h>
+#include <linux/types.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/tools/testing/selftests/memfd/memfd_test.c b/tools/testing/selftests/memfd/memfd_test.c
index 1d7e7b36bbdd..775c9e6c061e 100644
--- a/tools/testing/selftests/memfd/memfd_test.c
+++ b/tools/testing/selftests/memfd/memfd_test.c
@@ -36,6 +36,10 @@
#define MAX_PATH 256
#endif
+#ifndef MFD_NOEXEC_SEAL
+#define MFD_NOEXEC_SEAL 0x0008U
+#endif
+
/*
* Default is not to test hugetlbfs
*/
@@ -86,6 +90,21 @@ static int mfd_assert_new(const char *name, loff_t sz, unsigned int flags)
return fd;
}
+static void sysctl_assert_write(const char *val)
+{
+ int fd = open("/proc/sys/vm/memfd_noexec", O_WRONLY | O_CLOEXEC);
+
+ if (fd < 0) {
+ printf("open sysctl failed\n");
+ abort();
+ }
+
+ if (write(fd, val, strlen(val)) < 0) {
+ printf("write sysctl failed\n");
+ abort();
+ }
+}
+
static int mfd_assert_reopen_fd(int fd_in)
{
int fd;
@@ -764,6 +783,9 @@ static void test_create(void)
mfd_fail_new("", ~0);
mfd_fail_new("", 0x80000000U);
+ /* verify EXEC and NOEXEC_SEAL can't both be set */
+ mfd_fail_new("", MFD_EXEC | MFD_NOEXEC_SEAL);
+
/* verify MFD_CLOEXEC is allowed */
fd = mfd_assert_new("", 0, MFD_CLOEXEC);
close(fd);
@@ -975,9 +997,10 @@ static void test_seal_resize(void)
/*
* Test SEAL_EXEC
- * Test that chmod() cannot change x bits after sealing
+ * Test fd is created with exec and allow sealing.
+ * chmod() cannot change x bits after sealing.
*/
-static void test_seal_exec(void)
+static void test_exec_seal(void)
{
int fd;
@@ -985,10 +1008,9 @@ static void test_seal_exec(void)
fd = mfd_assert_new("kern_memfd_seal_exec",
mfd_def_size,
- MFD_CLOEXEC | MFD_ALLOW_SEALING);
+ MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_EXEC);
mfd_assert_mode(fd, 0777);
-
mfd_assert_chmod(fd, 0644);
mfd_assert_has_seals(fd, 0);
@@ -1006,6 +1028,131 @@ static void test_seal_exec(void)
close(fd);
}
+/*
+ * Test EXEC_NO_SEAL
+ * Test fd is created with exec and not allow sealing.
+ */
+static void test_exec_no_seal(void)
+{
+ int fd;
+
+ printf("%s EXEC_NO_SEAL\n", memfd_str);
+
+ /* Create with EXEC but without ALLOW_SEALING */
+ fd = mfd_assert_new("kern_memfd_exec_no_sealing",
+ mfd_def_size,
+ MFD_CLOEXEC | MFD_EXEC);
+ mfd_assert_mode(fd, 0777);
+ mfd_assert_has_seals(fd, F_SEAL_SEAL);
+ mfd_assert_chmod(fd, 0666);
+ close(fd);
+}
+
+/*
+ * Test memfd_create with MFD_NOEXEC flag
+ */
+static void test_noexec_seal(void)
+{
+ int fd;
+
+ printf("%s NOEXEC_SEAL\n", memfd_str);
+
+ /* Create with NOEXEC and ALLOW_SEALING */
+ fd = mfd_assert_new("kern_memfd_noexec",
+ mfd_def_size,
+ MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_NOEXEC_SEAL);
+ mfd_assert_mode(fd, 0666);
+ mfd_assert_has_seals(fd, F_SEAL_EXEC);
+ mfd_fail_chmod(fd, 0777);
+ close(fd);
+
+ /* Create with NOEXEC but without ALLOW_SEALING */
+ fd = mfd_assert_new("kern_memfd_noexec",
+ mfd_def_size,
+ MFD_CLOEXEC | MFD_NOEXEC_SEAL);
+ mfd_assert_mode(fd, 0666);
+ mfd_assert_has_seals(fd, F_SEAL_EXEC);
+ mfd_fail_chmod(fd, 0777);
+ close(fd);
+}
+
+static void test_sysctl_child(void)
+{
+ int fd, pid, ret;
+
+ printf("%s sysctl 0\n", memfd_str);
+ sysctl_assert_write("0");
+ fd = mfd_assert_new("kern_memfd_sysctl_0",
+ mfd_def_size,
+ MFD_CLOEXEC | MFD_ALLOW_SEALING);
+
+ mfd_assert_mode(fd, 0777);
+ mfd_assert_has_seals(fd, 0);
+ mfd_assert_chmod(fd, 0644);
+ close(fd);
+
+ printf("%s sysctl 1\n", memfd_str);
+ sysctl_assert_write("1");
+ fd = mfd_assert_new("kern_memfd_sysctl_1",
+ mfd_def_size,
+ MFD_CLOEXEC | MFD_ALLOW_SEALING);
+
+ mfd_assert_mode(fd, 0666);
+ mfd_assert_has_seals(fd, F_SEAL_EXEC);
+ mfd_fail_chmod(fd, 0777);
+ close(fd);
+
+ printf("%s sysctl 2\n", memfd_str);
+ sysctl_assert_write("2");
+ mfd_fail_new("kern_memfd_sysctl_2",
+ MFD_CLOEXEC | MFD_ALLOW_SEALING);
+}
+
+static int newpid_thread_fn(void *arg)
+{
+ test_sysctl_child();
+ return 0;
+}
+
+static pid_t spawn_newpid_thread(unsigned int flags)
+{
+ uint8_t *stack;
+ pid_t pid;
+
+ stack = malloc(STACK_SIZE);
+ if (!stack) {
+ printf("malloc(STACK_SIZE) failed: %m\n");
+ abort();
+ }
+
+ pid = clone(newpid_thread_fn,
+ stack + STACK_SIZE,
+ SIGCHLD | flags,
+ NULL);
+ if (pid < 0) {
+ printf("clone() failed: %m\n");
+ abort();
+ }
+
+ return pid;
+}
+
+static void join_newpid_thread(pid_t pid)
+{
+ waitpid(pid, NULL, 0);
+}
+
+/*
+ * Test sysctl
+ * A very basic sealing test to see whether setting/retrieving seals works.
+ */
+static void test_sysctl(void)
+{
+ int pid = spawn_newpid_thread(CLONE_NEWPID);
+
+ join_newpid_thread(pid);
+}
+
/*
* Test sharing via dup()
* Test that seals are shared between dupped FDs and they're all equal.
@@ -1179,13 +1326,15 @@ int main(int argc, char **argv)
test_create();
test_basic();
+ test_exec_seal();
+ test_exec_no_seal();
+ test_noexec_seal();
test_seal_write();
test_seal_future_write();
test_seal_shrink();
test_seal_grow();
test_seal_resize();
- test_seal_exec();
test_share_dup("SHARE-DUP", "");
test_share_mmap("SHARE-MMAP", "");
@@ -1201,6 +1350,8 @@ int main(int argc, char **argv)
test_share_fork("SHARE-FORK", SHARED_FT_STR);
join_idle_thread(pid);
+ test_sysctl();
+
printf("memfd: DONE\n");
return 0;
--
2.39.0.rc0.267.gcb52ba06e7-goog
next prev parent reply other threads:[~2022-12-02 1:36 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-12-02 1:33 [PATCH v3] mm/memfd: MFD_NOEXEC_SEAL and MFD_EXEC jeffxu
2022-12-02 1:33 ` [PATCH v3] mm/memfd: add F_SEAL_EXEC jeffxu
2022-12-02 22:43 ` Kees Cook
2022-12-02 22:45 ` Kees Cook
2022-12-02 1:34 ` [PATCH v3] mm/memfd: add MFD_NOEXEC_SEAL and MFD_EXEC jeffxu
2022-12-02 11:32 ` kernel test robot
2022-12-02 13:33 ` kernel test robot
2022-12-02 13:43 ` kernel test robot
2022-12-02 22:56 ` Kees Cook
2022-12-02 23:32 ` Jeff Xu
2022-12-02 1:34 ` [PATCH v3] selftests/memfd: add tests for F_SEAL_EXEC jeffxu
2022-12-02 1:34 ` jeffxu [this message]
2022-12-02 1:34 ` [PATCH v3] mm/memfd: security hook for memfd_create jeffxu
2022-12-02 10:11 ` kernel test robot
2022-12-02 12:33 ` kernel test robot
2022-12-02 22:58 ` Kees Cook
2022-12-02 23:23 ` Jeff Xu
2022-12-02 1:34 ` [PATCH v3] mm/memfd: Add write seals when apply SEAL_EXEC to executable memfd jeffxu
2022-12-02 23:23 ` Daniel Verkamp
2022-12-03 2:29 ` Jeff Xu
2022-12-02 22:41 ` [PATCH v3] mm/memfd: MFD_NOEXEC_SEAL and MFD_EXEC Kees Cook
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20221202013404.163143-5-jeffxu@google.com \
--to=jeffxu@chromium.org \
--cc=akpm@linux-foundation.org \
--cc=dmitry.torokhov@gmail.com \
--cc=dverkamp@chromium.org \
--cc=hughd@google.com \
--cc=jannh@google.com \
--cc=jeffxu@google.com \
--cc=jorgelo@chromium.org \
--cc=keescook@chromium.org \
--cc=linux-hardening@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=mnissler@chromium.org \
--cc=skhan@linuxfoundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.