From: Kees Cook <kees@kernel.org>
To: Mark Brown <broonie@kernel.org>
Cc: "Rick P. Edgecombe" <rick.p.edgecombe@intel.com>,
Deepak Gupta <debug@rivosinc.com>,
Szabolcs Nagy <Szabolcs.Nagy@arm.com>,
"H.J. Lu" <hjl.tools@gmail.com>,
Florian Weimer <fweimer@redhat.com>,
Thomas Gleixner <tglx@linutronix.de>,
Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>,
Peter Zijlstra <peterz@infradead.org>,
Juri Lelli <juri.lelli@redhat.com>,
Vincent Guittot <vincent.guittot@linaro.org>,
Dietmar Eggemann <dietmar.eggemann@arm.com>,
Steven Rostedt <rostedt@goodmis.org>,
Ben Segall <bsegall@google.com>, Mel Gorman <mgorman@suse.de>,
Daniel Bristot de Oliveira <bristot@redhat.com>,
Valentin Schneider <vschneid@redhat.com>,
Christian Brauner <brauner@kernel.org>,
Shuah Khan <shuah@kernel.org>,
linux-kernel@vger.kernel.org,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>,
jannh@google.com, linux-kselftest@vger.kernel.org,
linux-api@vger.kernel.org
Subject: Re: [PATCH RFT v7 9/9] selftests/clone3: Test shadow stack support
Date: Mon, 5 Aug 2024 20:54:54 -0700 [thread overview]
Message-ID: <202408052046.00BC7CBC@keescook> (raw)
In-Reply-To: <20240731-clone3-shadow-stack-v7-9-a9532eebfb1d@kernel.org>
On Wed, Jul 31, 2024 at 01:14:15PM +0100, Mark Brown wrote:
> Add basic test coverage for specifying the shadow stack for a newly
> created thread via clone3(), including coverage of the newly extended
> argument structure. We check that a user specified shadow stack can be
> provided, and that invalid combinations of parameters are rejected.
>
> In order to facilitate testing on systems without userspace shadow stack
> support we manually enable shadow stacks on startup, this is architecture
> specific due to the use of an arch_prctl() on x86. Due to interactions with
> potential userspace locking of features we actually detect support for
> shadow stacks on the running system by attempting to allocate a shadow
> stack page during initialisation using map_shadow_stack(), warning if this
> succeeds when the enable failed.
>
> In order to allow testing of user configured shadow stacks on
> architectures with that feature we need to ensure that we do not return
> from the function where the clone3() syscall is called in the child
> process, doing so would trigger a shadow stack underflow. To do this we
> use inline assembly rather than the standard syscall wrapper to call
> clone3(). In order to avoid surprises we also use a syscall rather than
> the libc exit() function., this should be overly cautious.
>
> Signed-off-by: Mark Brown <broonie@kernel.org>
> ---
> tools/testing/selftests/clone3/clone3.c | 134 +++++++++++++++++++++-
> tools/testing/selftests/clone3/clone3_selftests.h | 38 ++++++
> 2 files changed, 171 insertions(+), 1 deletion(-)
>
> diff --git a/tools/testing/selftests/clone3/clone3.c b/tools/testing/selftests/clone3/clone3.c
> index 26221661e9ae..81c2e8648e8b 100644
> --- a/tools/testing/selftests/clone3/clone3.c
> +++ b/tools/testing/selftests/clone3/clone3.c
> @@ -3,6 +3,7 @@
> /* Based on Christian Brauner's clone3() example */
>
> #define _GNU_SOURCE
> +#include <asm/mman.h>
> #include <errno.h>
> #include <inttypes.h>
> #include <linux/types.h>
> @@ -11,6 +12,7 @@
> #include <stdint.h>
> #include <stdio.h>
> #include <stdlib.h>
> +#include <sys/mman.h>
> #include <sys/syscall.h>
> #include <sys/types.h>
> #include <sys/un.h>
> @@ -19,8 +21,12 @@
> #include <sched.h>
>
> #include "../kselftest.h"
> +#include "../ksft_shstk.h"
> #include "clone3_selftests.h"
>
> +static bool shadow_stack_supported;
> +static size_t max_supported_args_size;
> +
> enum test_mode {
> CLONE3_ARGS_NO_TEST,
> CLONE3_ARGS_ALL_0,
> @@ -28,6 +34,10 @@ enum test_mode {
> CLONE3_ARGS_INVAL_EXIT_SIGNAL_NEG,
> CLONE3_ARGS_INVAL_EXIT_SIGNAL_CSIG,
> CLONE3_ARGS_INVAL_EXIT_SIGNAL_NSIG,
> + CLONE3_ARGS_SHADOW_STACK,
> + CLONE3_ARGS_SHADOW_STACK_NO_SIZE,
> + CLONE3_ARGS_SHADOW_STACK_NO_POINTER,
> + CLONE3_ARGS_SHADOW_STACK_NO_TOKEN,
> };
>
> typedef bool (*filter_function)(void);
> @@ -44,6 +54,44 @@ struct test {
> filter_function filter;
> };
>
> +
> +/*
> + * We check for shadow stack support by attempting to use
> + * map_shadow_stack() since features may have been locked by the
> + * dynamic linker resulting in spurious errors when we attempt to
> + * enable on startup. We warn if the enable failed.
> + */
> +static void test_shadow_stack_supported(void)
> +{
> + long ret;
> +
> + ret = syscall(__NR_map_shadow_stack, 0, getpagesize(), 0);
> + if (ret == -1) {
> + ksft_print_msg("map_shadow_stack() not supported\n");
> + } else if ((void *)ret == MAP_FAILED) {
> + ksft_print_msg("Failed to map shadow stack\n");
> + } else {
> + ksft_print_msg("Shadow stack supportd\n");
typo: supportd -> supported
> + shadow_stack_supported = true;
> +
> + if (!shadow_stack_enabled)
> + ksft_print_msg("Mapped but did not enable shadow stack\n");
> + }
> +}
On my CET system, this reports:
...
# clone3() syscall supported
# Shadow stack supportd
# Running test 'simple clone3()'
...
(happily doesn't print "Mapped but did not enable ...").
> +
> +static unsigned long long get_shadow_stack_page(unsigned long flags)
> +{
> + unsigned long long page;
> +
> + page = syscall(__NR_map_shadow_stack, 0, getpagesize(), flags);
> + if ((void *)page == MAP_FAILED) {
> + ksft_print_msg("map_shadow_stack() failed: %d\n", errno);
> + return 0;
> + }
> +
> + return page;
> +}
> +
> static int call_clone3(uint64_t flags, size_t size, enum test_mode test_mode)
> {
> struct __clone_args args = {
> @@ -89,6 +137,21 @@ static int call_clone3(uint64_t flags, size_t size, enum test_mode test_mode)
> case CLONE3_ARGS_INVAL_EXIT_SIGNAL_NSIG:
> args.exit_signal = 0x00000000000000f0ULL;
> break;
> + case CLONE3_ARGS_SHADOW_STACK:
> + /* We need to specify a normal stack too to avoid corruption */
> + args.shadow_stack = get_shadow_stack_page(SHADOW_STACK_SET_TOKEN);
> + args.shadow_stack_size = getpagesize();
> + break;
# Running test 'Shadow stack on system with shadow stack'
# [5496] Trying clone3() with flags 0 (size 0)
# I am the parent (5496). My child's pid is 5505
# Child exited with signal 11
# [5496] clone3() with flags says: 11 expected 0
# [5496] Result (11) is different than expected (0)
not ok 20 Shadow stack on system with shadow stack
The child segfaults immediately, it seems?
> + case CLONE3_ARGS_SHADOW_STACK_NO_POINTER:
> + args.shadow_stack_size = getpagesize();
> + break;
# Running test 'Shadow stack with no pointer'
# [5496] Trying clone3() with flags 0 (size 0)
# Invalid argument - Failed to create new process
# [5496] clone3() with flags says: -22 expected -22
ok 21 Shadow stack with no pointer
This seems like it misses the failure and reports ok
> + case CLONE3_ARGS_SHADOW_STACK_NO_SIZE:
> + args.shadow_stack = get_shadow_stack_page(SHADOW_STACK_SET_TOKEN);
> + break;
# Running test 'Shadow stack with no size'
# [5496] Trying clone3() with flags 0 (size 0)
# Invalid argument - Failed to create new process
# [5496] clone3() with flags says: -22 expected -22
ok 22 Shadow stack with no size
Same?
> + case CLONE3_ARGS_SHADOW_STACK_NO_TOKEN:
> + args.shadow_stack = get_shadow_stack_page(0);
> + args.shadow_stack_size = getpagesize();
> + break;
This actually segfaults the parent:
# Running test 'Shadow stack with no token'
# [5496] Trying clone3() with flags 0x100 (size 0)
# I am the parent (5496). My child's pid is 5507
Segmentation fault
Let me know what would be most helpful to dig into more...
--
Kees Cook
next prev parent reply other threads:[~2024-08-06 3:54 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-31 12:14 [PATCH RFT v7 0/9] fork: Support shadow stacks in clone3() Mark Brown
2024-07-31 12:14 ` [PATCH RFT v7 1/9] Documentation: userspace-api: Add shadow stack API documentation Mark Brown
2024-07-31 12:14 ` [PATCH RFT v7 2/9] selftests: Provide helper header for shadow stack testing Mark Brown
2024-07-31 12:14 ` [PATCH RFT v7 3/9] mm: Introduce ARCH_HAS_USER_SHADOW_STACK Mark Brown
2024-07-31 12:14 ` [PATCH RFT v7 4/9] fork: Add shadow stack support to clone3() Mark Brown
2024-07-31 12:14 ` [PATCH RFT v7 5/9] selftests/clone3: Remove redundant flushes of output streams Mark Brown
2024-07-31 12:14 ` [PATCH RFT v7 6/9] selftests/clone3: Factor more of main loop into test_clone3() Mark Brown
2024-07-31 12:14 ` [PATCH RFT v7 7/9] selftests/clone3: Explicitly handle child exits due to signals Mark Brown
2024-07-31 12:14 ` [PATCH RFT v7 8/9] selftests/clone3: Allow tests to flag if -E2BIG is a valid error code Mark Brown
2024-07-31 12:14 ` [PATCH RFT v7 9/9] selftests/clone3: Test shadow stack support Mark Brown
2024-08-06 3:54 ` Kees Cook [this message]
2024-08-06 15:10 ` Mark Brown
2024-08-07 5:08 ` Kees Cook
2024-08-07 12:39 ` Mark Brown
2024-08-07 18:23 ` Kees Cook
2024-08-07 19:23 ` Kees Cook
2024-08-07 22:03 ` Mark Brown
2024-08-07 23:22 ` Kees Cook
2024-08-06 20:10 ` Mark Brown
2024-08-06 21:43 ` Kees Cook
2024-08-06 21:57 ` Mark Brown
2024-08-06 22:21 ` Mark Brown
2024-08-05 21:29 ` [PATCH RFT v7 0/9] fork: Support shadow stacks in clone3() Shuah Khan
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=202408052046.00BC7CBC@keescook \
--to=kees@kernel.org \
--cc=Szabolcs.Nagy@arm.com \
--cc=bp@alien8.de \
--cc=brauner@kernel.org \
--cc=bristot@redhat.com \
--cc=broonie@kernel.org \
--cc=bsegall@google.com \
--cc=catalin.marinas@arm.com \
--cc=dave.hansen@linux.intel.com \
--cc=debug@rivosinc.com \
--cc=dietmar.eggemann@arm.com \
--cc=fweimer@redhat.com \
--cc=hjl.tools@gmail.com \
--cc=hpa@zytor.com \
--cc=jannh@google.com \
--cc=juri.lelli@redhat.com \
--cc=linux-api@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=mgorman@suse.de \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
--cc=rick.p.edgecombe@intel.com \
--cc=rostedt@goodmis.org \
--cc=shuah@kernel.org \
--cc=tglx@linutronix.de \
--cc=vincent.guittot@linaro.org \
--cc=vschneid@redhat.com \
--cc=will@kernel.org \
--cc=x86@kernel.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.