From: Kees Cook <keescook@chromium.org> To: Joey Gouly <joey.gouly@arm.com> Cc: "Catalin Marinas" <catalin.marinas@arm.com>, "Andrew Morton" <akpm@linux-foundation.org>, "Lennart Poettering" <lennart@poettering.net>, "Zbigniew Jędrzejewski-Szmek" <zbyszek@in.waw.pl>, "Alexander Viro" <viro@zeniv.linux.org.uk>, "Szabolcs Nagy" <szabolcs.nagy@arm.com>, "Mark Brown" <broonie@kernel.org>, "Jeremy Linton" <jeremy.linton@arm.com>, "Topi Miettinen" <toiwoton@gmail.com>, linux-mm@kvack.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-abi-devel@lists.sourceforge.net, nd@arm.com, shuah@kernel.org Subject: Re: [PATCH v1 2/2] kselftest: vm: add tests for memory-deny-write-execute Date: Fri, 28 Oct 2022 13:16:43 -0700 [thread overview] Message-ID: <202210281314.C5D3414722@keescook> (raw) In-Reply-To: <20221026150457.36957-3-joey.gouly@arm.com> Here's an alternative rewritten to use kselftest_harness.h, with tests for the prctl() flags, and the missed Makefile addition. This should be much easier to add more variants and tests to, I hope. -Kees From bc442a99ebd9852bfaa7444b521bd55fdbb4d369 Mon Sep 17 00:00:00 2001 From: Kees Cook <keescook@chromium.org> Date: Fri, 28 Oct 2022 13:10:45 -0700 Subject: [PATCH] selftests/vm: add tests for memory-deny-write-execute Add tests for new prctl() commands, including flag values. Add tests for new denials based on PROT_EXEC across mmap() and mprotect() with MDWE. Co-developed-by: Joey Gouly <joey.gouly@arm.com> Signed-off-by: Joey Gouly <joey.gouly@arm.com> Signed-off-by: Kees Cook <keescook@chromium.org> --- tools/testing/selftests/vm/Makefile | 1 + tools/testing/selftests/vm/mdwe_test.c | 201 +++++++++++++++++++++++++ 2 files changed, 202 insertions(+) create mode 100644 tools/testing/selftests/vm/mdwe_test.c diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile index 163c2fde3cb3..8dd4d4910fa5 100644 --- a/tools/testing/selftests/vm/Makefile +++ b/tools/testing/selftests/vm/Makefile @@ -52,6 +52,7 @@ TEST_GEN_FILES += userfaultfd TEST_GEN_PROGS += soft-dirty TEST_GEN_PROGS += split_huge_page_test TEST_GEN_FILES += ksm_tests +TEST_GEN_PROGS += mdwe_test ifeq ($(MACHINE),x86_64) CAN_BUILD_I386 := $(shell ./../x86/check_cc.sh "$(CC)" ../x86/trivial_32bit_program.c -m32) diff --git a/tools/testing/selftests/vm/mdwe_test.c b/tools/testing/selftests/vm/mdwe_test.c new file mode 100644 index 000000000000..d6f6b751bcd6 --- /dev/null +++ b/tools/testing/selftests/vm/mdwe_test.c @@ -0,0 +1,201 @@ +// SPDX-License-Identifier: GPL-2.0 +#ifdef __aarch64__ +#include <asm/hwcap.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <sys/auxv.h> +#include <sys/mman.h> +#include <sys/prctl.h> +#include <sys/wait.h> +#include <unistd.h> + +#include <linux/prctl.h> + +#include "../kselftest_harness.h" + +#define PR_SET_MDWE 65 +# define PR_MDWE_FLAG_MMAP 1 + +#define PR_GET_MDWE 66 + +#ifdef __aarch64__ +# define PROT_BTI 0x10 /* BTI guarded page */ +#else +# define PROT_BTI 0 +#endif + +TEST(prctl_flags) +{ + EXPECT_LT(prctl(PR_SET_MDWE, 7, 0, 0, 0), 0); + EXPECT_LT(prctl(PR_SET_MDWE, 0, 7, 0, 0), 0); + EXPECT_LT(prctl(PR_SET_MDWE, 0, 0, 7, 0), 0); + EXPECT_LT(prctl(PR_SET_MDWE, 0, 0, 0, 7), 0); + + EXPECT_LT(prctl(PR_GET_MDWE, 7, 0, 0, 0), 0); + EXPECT_LT(prctl(PR_GET_MDWE, 0, 7, 0, 0), 0); + EXPECT_LT(prctl(PR_GET_MDWE, 0, 0, 7, 0), 0); + EXPECT_LT(prctl(PR_GET_MDWE, 0, 0, 0, 7), 0); +} + +FIXTURE(mdwe) +{ + void *p; + int flags; + size_t size; + pid_t pid; +}; + +FIXTURE_VARIANT(mdwe) +{ + bool enabled; + bool forked; +}; + +FIXTURE_VARIANT_ADD(mdwe, stock) +{ + .enabled = false, + .forked = false, +}; + +FIXTURE_VARIANT_ADD(mdwe, enabled) +{ + .enabled = true, + .forked = false, +}; + +FIXTURE_VARIANT_ADD(mdwe, forked) +{ + .enabled = true, + .forked = true, +}; + +FIXTURE_SETUP(mdwe) +{ + int ret, status; + + self->p = NULL; + self->flags = MAP_SHARED | MAP_ANONYMOUS; + self->size = getpagesize(); + + if (!variant->enabled) + return; + + ret = prctl(PR_SET_MDWE, PR_MDWE_FLAG_MMAP, 0, 0, 0); + ASSERT_EQ(ret, 0) { + TH_LOG("PR_SET_MDWE failed or unsupported"); + } + + ret = prctl(PR_GET_MDWE, 0, 0, 0, 0); + ASSERT_EQ(ret, 1); + + if (variant->forked) { + self->pid = fork(); + ASSERT_GE(self->pid, 0) { + TH_LOG("fork failed\n"); + } + + if (self->pid > 0) { + ret = waitpid(self->pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + exit(WEXITSTATUS(status)); + } + } +} + +FIXTURE_TEARDOWN(mdwe) +{ + if (self->p && self->p != MAP_FAILED) + munmap(self->p, self->size); +} + +TEST_F(mdwe, mmap_READ_EXEC) +{ + self->p = mmap(NULL, self->size, PROT_READ | PROT_EXEC, self->flags, 0, 0); + EXPECT_NE(self->p, MAP_FAILED); +} + +TEST_F(mdwe, mmap_WRITE_EXEC) +{ + self->p = mmap(NULL, self->size, PROT_WRITE | PROT_EXEC, self->flags, 0, 0); + if (variant->enabled) { + EXPECT_EQ(self->p, MAP_FAILED); + } else { + EXPECT_NE(self->p, MAP_FAILED); + } +} + +TEST_F(mdwe, mprotect_stay_EXEC) +{ + int ret; + + self->p = mmap(NULL, self->size, PROT_READ | PROT_EXEC, self->flags, 0, 0); + ASSERT_NE(self->p, MAP_FAILED); + + ret = mprotect(self->p, self->size, PROT_READ | PROT_EXEC); + EXPECT_EQ(ret, 0); +} + +TEST_F(mdwe, mprotect_add_EXEC) +{ + int ret; + + self->p = mmap(NULL, self->size, PROT_READ, self->flags, 0, 0); + ASSERT_NE(self->p, MAP_FAILED); + + ret = mprotect(self->p, self->size, PROT_READ | PROT_EXEC); + if (variant->enabled) { + EXPECT_LT(ret, 0); + } else { + EXPECT_EQ(ret, 0); + } +} + +TEST_F(mdwe, mprotect_WRITE_EXEC) +{ + int ret; + + self->p = mmap(NULL, self->size, PROT_WRITE, self->flags, 0, 0); + ASSERT_NE(self->p, MAP_FAILED); + + ret = mprotect(self->p, self->size, PROT_WRITE | PROT_EXEC); + if (variant->enabled) { + EXPECT_LT(ret, 0); + } else { + EXPECT_EQ(ret, 0); + } +} + +TEST_F(mdwe, mmap_FIXED) +{ + void *p; + + self->p = mmap(NULL, self->size, PROT_READ, self->flags, 0, 0); + ASSERT_NE(self->p, MAP_FAILED); + + p = mmap(self->p, self->size, PROT_READ | PROT_EXEC, + self->flags | MAP_FIXED, 0, 0); + if (variant->enabled) { + EXPECT_EQ(p, MAP_FAILED); + } else { + EXPECT_EQ(p, self->p); + } +} + +TEST_F(mdwe, arm64_BTI) +{ + int ret; + +#ifdef __aarch64__ + if (!(getauxval(AT_HWCAP2) & HWCAP2_BTI)) +#endif + SKIP(return, "HWCAP2_BTI not supported"); + + self->p = mmap(NULL, self->size, PROT_EXEC, self->flags, 0, 0); + ASSERT_NE(self->p, MAP_FAILED); + + ret = mprotect(self->p, self->size, PROT_EXEC | PROT_BTI); + EXPECT_EQ(ret, 0); +} + +TEST_HARNESS_MAIN -- 2.34.1 -- Kees Cook
WARNING: multiple messages have this Message-ID (diff)
From: Kees Cook <keescook@chromium.org> To: Joey Gouly <joey.gouly@arm.com> Cc: "Catalin Marinas" <catalin.marinas@arm.com>, "Andrew Morton" <akpm@linux-foundation.org>, "Lennart Poettering" <lennart@poettering.net>, "Zbigniew Jędrzejewski-Szmek" <zbyszek@in.waw.pl>, "Alexander Viro" <viro@zeniv.linux.org.uk>, "Szabolcs Nagy" <szabolcs.nagy@arm.com>, "Mark Brown" <broonie@kernel.org>, "Jeremy Linton" <jeremy.linton@arm.com>, "Topi Miettinen" <toiwoton@gmail.com>, linux-mm@kvack.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-abi-devel@lists.sourceforge.net, nd@arm.com, shuah@kernel.org Subject: Re: [PATCH v1 2/2] kselftest: vm: add tests for memory-deny-write-execute Date: Fri, 28 Oct 2022 13:16:43 -0700 [thread overview] Message-ID: <202210281314.C5D3414722@keescook> (raw) In-Reply-To: <20221026150457.36957-3-joey.gouly@arm.com> Here's an alternative rewritten to use kselftest_harness.h, with tests for the prctl() flags, and the missed Makefile addition. This should be much easier to add more variants and tests to, I hope. -Kees From bc442a99ebd9852bfaa7444b521bd55fdbb4d369 Mon Sep 17 00:00:00 2001 From: Kees Cook <keescook@chromium.org> Date: Fri, 28 Oct 2022 13:10:45 -0700 Subject: [PATCH] selftests/vm: add tests for memory-deny-write-execute Add tests for new prctl() commands, including flag values. Add tests for new denials based on PROT_EXEC across mmap() and mprotect() with MDWE. Co-developed-by: Joey Gouly <joey.gouly@arm.com> Signed-off-by: Joey Gouly <joey.gouly@arm.com> Signed-off-by: Kees Cook <keescook@chromium.org> --- tools/testing/selftests/vm/Makefile | 1 + tools/testing/selftests/vm/mdwe_test.c | 201 +++++++++++++++++++++++++ 2 files changed, 202 insertions(+) create mode 100644 tools/testing/selftests/vm/mdwe_test.c diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile index 163c2fde3cb3..8dd4d4910fa5 100644 --- a/tools/testing/selftests/vm/Makefile +++ b/tools/testing/selftests/vm/Makefile @@ -52,6 +52,7 @@ TEST_GEN_FILES += userfaultfd TEST_GEN_PROGS += soft-dirty TEST_GEN_PROGS += split_huge_page_test TEST_GEN_FILES += ksm_tests +TEST_GEN_PROGS += mdwe_test ifeq ($(MACHINE),x86_64) CAN_BUILD_I386 := $(shell ./../x86/check_cc.sh "$(CC)" ../x86/trivial_32bit_program.c -m32) diff --git a/tools/testing/selftests/vm/mdwe_test.c b/tools/testing/selftests/vm/mdwe_test.c new file mode 100644 index 000000000000..d6f6b751bcd6 --- /dev/null +++ b/tools/testing/selftests/vm/mdwe_test.c @@ -0,0 +1,201 @@ +// SPDX-License-Identifier: GPL-2.0 +#ifdef __aarch64__ +#include <asm/hwcap.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <sys/auxv.h> +#include <sys/mman.h> +#include <sys/prctl.h> +#include <sys/wait.h> +#include <unistd.h> + +#include <linux/prctl.h> + +#include "../kselftest_harness.h" + +#define PR_SET_MDWE 65 +# define PR_MDWE_FLAG_MMAP 1 + +#define PR_GET_MDWE 66 + +#ifdef __aarch64__ +# define PROT_BTI 0x10 /* BTI guarded page */ +#else +# define PROT_BTI 0 +#endif + +TEST(prctl_flags) +{ + EXPECT_LT(prctl(PR_SET_MDWE, 7, 0, 0, 0), 0); + EXPECT_LT(prctl(PR_SET_MDWE, 0, 7, 0, 0), 0); + EXPECT_LT(prctl(PR_SET_MDWE, 0, 0, 7, 0), 0); + EXPECT_LT(prctl(PR_SET_MDWE, 0, 0, 0, 7), 0); + + EXPECT_LT(prctl(PR_GET_MDWE, 7, 0, 0, 0), 0); + EXPECT_LT(prctl(PR_GET_MDWE, 0, 7, 0, 0), 0); + EXPECT_LT(prctl(PR_GET_MDWE, 0, 0, 7, 0), 0); + EXPECT_LT(prctl(PR_GET_MDWE, 0, 0, 0, 7), 0); +} + +FIXTURE(mdwe) +{ + void *p; + int flags; + size_t size; + pid_t pid; +}; + +FIXTURE_VARIANT(mdwe) +{ + bool enabled; + bool forked; +}; + +FIXTURE_VARIANT_ADD(mdwe, stock) +{ + .enabled = false, + .forked = false, +}; + +FIXTURE_VARIANT_ADD(mdwe, enabled) +{ + .enabled = true, + .forked = false, +}; + +FIXTURE_VARIANT_ADD(mdwe, forked) +{ + .enabled = true, + .forked = true, +}; + +FIXTURE_SETUP(mdwe) +{ + int ret, status; + + self->p = NULL; + self->flags = MAP_SHARED | MAP_ANONYMOUS; + self->size = getpagesize(); + + if (!variant->enabled) + return; + + ret = prctl(PR_SET_MDWE, PR_MDWE_FLAG_MMAP, 0, 0, 0); + ASSERT_EQ(ret, 0) { + TH_LOG("PR_SET_MDWE failed or unsupported"); + } + + ret = prctl(PR_GET_MDWE, 0, 0, 0, 0); + ASSERT_EQ(ret, 1); + + if (variant->forked) { + self->pid = fork(); + ASSERT_GE(self->pid, 0) { + TH_LOG("fork failed\n"); + } + + if (self->pid > 0) { + ret = waitpid(self->pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + exit(WEXITSTATUS(status)); + } + } +} + +FIXTURE_TEARDOWN(mdwe) +{ + if (self->p && self->p != MAP_FAILED) + munmap(self->p, self->size); +} + +TEST_F(mdwe, mmap_READ_EXEC) +{ + self->p = mmap(NULL, self->size, PROT_READ | PROT_EXEC, self->flags, 0, 0); + EXPECT_NE(self->p, MAP_FAILED); +} + +TEST_F(mdwe, mmap_WRITE_EXEC) +{ + self->p = mmap(NULL, self->size, PROT_WRITE | PROT_EXEC, self->flags, 0, 0); + if (variant->enabled) { + EXPECT_EQ(self->p, MAP_FAILED); + } else { + EXPECT_NE(self->p, MAP_FAILED); + } +} + +TEST_F(mdwe, mprotect_stay_EXEC) +{ + int ret; + + self->p = mmap(NULL, self->size, PROT_READ | PROT_EXEC, self->flags, 0, 0); + ASSERT_NE(self->p, MAP_FAILED); + + ret = mprotect(self->p, self->size, PROT_READ | PROT_EXEC); + EXPECT_EQ(ret, 0); +} + +TEST_F(mdwe, mprotect_add_EXEC) +{ + int ret; + + self->p = mmap(NULL, self->size, PROT_READ, self->flags, 0, 0); + ASSERT_NE(self->p, MAP_FAILED); + + ret = mprotect(self->p, self->size, PROT_READ | PROT_EXEC); + if (variant->enabled) { + EXPECT_LT(ret, 0); + } else { + EXPECT_EQ(ret, 0); + } +} + +TEST_F(mdwe, mprotect_WRITE_EXEC) +{ + int ret; + + self->p = mmap(NULL, self->size, PROT_WRITE, self->flags, 0, 0); + ASSERT_NE(self->p, MAP_FAILED); + + ret = mprotect(self->p, self->size, PROT_WRITE | PROT_EXEC); + if (variant->enabled) { + EXPECT_LT(ret, 0); + } else { + EXPECT_EQ(ret, 0); + } +} + +TEST_F(mdwe, mmap_FIXED) +{ + void *p; + + self->p = mmap(NULL, self->size, PROT_READ, self->flags, 0, 0); + ASSERT_NE(self->p, MAP_FAILED); + + p = mmap(self->p, self->size, PROT_READ | PROT_EXEC, + self->flags | MAP_FIXED, 0, 0); + if (variant->enabled) { + EXPECT_EQ(p, MAP_FAILED); + } else { + EXPECT_EQ(p, self->p); + } +} + +TEST_F(mdwe, arm64_BTI) +{ + int ret; + +#ifdef __aarch64__ + if (!(getauxval(AT_HWCAP2) & HWCAP2_BTI)) +#endif + SKIP(return, "HWCAP2_BTI not supported"); + + self->p = mmap(NULL, self->size, PROT_EXEC, self->flags, 0, 0); + ASSERT_NE(self->p, MAP_FAILED); + + ret = mprotect(self->p, self->size, PROT_EXEC | PROT_BTI); + EXPECT_EQ(ret, 0); +} + +TEST_HARNESS_MAIN -- 2.34.1 -- Kees Cook _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2022-10-28 20:16 UTC|newest] Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top 2022-10-26 15:04 [PATCH v1 0/2] mm: In-kernel support for memory-deny-write-execute (MDWE) Joey Gouly 2022-10-26 15:04 ` Joey Gouly 2022-10-26 15:04 ` [PATCH v1 1/2] mm: Implement memory-deny-write-execute as a prctl Joey Gouly 2022-10-26 15:04 ` Joey Gouly 2022-10-28 18:51 ` Kees Cook 2022-10-28 18:51 ` Kees Cook 2022-11-10 11:27 ` Joey Gouly 2022-11-10 11:27 ` Joey Gouly 2022-11-10 12:03 ` Catalin Marinas 2022-11-10 12:03 ` Catalin Marinas 2022-11-12 6:11 ` Topi Miettinen 2022-11-12 6:11 ` Topi Miettinen 2022-11-15 15:35 ` Catalin Marinas 2022-11-15 15:35 ` Catalin Marinas 2022-11-15 19:31 ` Topi Miettinen 2022-11-15 19:31 ` Topi Miettinen 2022-10-26 15:04 ` [PATCH v1 2/2] kselftest: vm: add tests for memory-deny-write-execute Joey Gouly 2022-10-26 15:04 ` Joey Gouly 2022-10-28 17:03 ` Mark Brown 2022-10-28 17:03 ` Mark Brown 2022-11-08 17:33 ` Joey Gouly 2022-11-08 17:33 ` Joey Gouly 2022-11-09 13:33 ` Mark Brown 2022-11-09 13:33 ` Mark Brown 2022-10-28 17:45 ` Kees Cook 2022-10-28 17:45 ` Kees Cook 2022-10-28 20:16 ` Kees Cook [this message] 2022-10-28 20:16 ` Kees Cook 2022-11-07 12:23 ` Szabolcs Nagy 2022-11-07 12:23 ` Szabolcs Nagy 2022-10-28 20:19 ` Kees Cook 2022-10-28 20:19 ` Kees Cook 2022-11-06 19:42 ` [PATCH v1 0/2] mm: In-kernel support for memory-deny-write-execute (MDWE) Topi Miettinen 2022-11-06 19:42 ` Topi Miettinen
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=202210281314.C5D3414722@keescook \ --to=keescook@chromium.org \ --cc=akpm@linux-foundation.org \ --cc=broonie@kernel.org \ --cc=catalin.marinas@arm.com \ --cc=jeremy.linton@arm.com \ --cc=joey.gouly@arm.com \ --cc=lennart@poettering.net \ --cc=linux-abi-devel@lists.sourceforge.net \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-mm@kvack.org \ --cc=nd@arm.com \ --cc=shuah@kernel.org \ --cc=szabolcs.nagy@arm.com \ --cc=toiwoton@gmail.com \ --cc=viro@zeniv.linux.org.uk \ --cc=zbyszek@in.waw.pl \ /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: linkBe 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.