Add a test that locks the shadow stack write bit and then attempts to disable write. The disable should fail with EPERM since it's in a locked state. This also preserves the write bit being set for the whole test suite as well as preserving the ability to unlock at the end.
Signed-off-by: Bill Roberts <[email protected]> --- .../testing/selftests/x86/test_shadow_stack.c | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tools/testing/selftests/x86/test_shadow_stack.c b/tools/testing/selftests/x86/test_shadow_stack.c index b52c5420c137..72e7329d89d7 100644 --- a/tools/testing/selftests/x86/test_shadow_stack.c +++ b/tools/testing/selftests/x86/test_shadow_stack.c @@ -1060,6 +1060,24 @@ int test_ptrace(void) return 1; } +static int test_locking(void) +{ + + if (ARCH_PRCTL(ARCH_SHSTK_LOCK, ARCH_SHSTK_WRSS)) { + printf("[FAIL]\tCould not lock Shadow stack write\n"); + return 1; + } + + if (ARCH_PRCTL(ARCH_SHSTK_DISABLE, ARCH_SHSTK_WRSS) != -EPERM) { + printf("[FAIL]\tCould change Shadow stack write after lock\n"); + return 1; + } + + printf("[OK]\tShadow stack locking\n"); + + return 0; +} + int main(int argc, char *argv[]) { int ret = 0; @@ -1079,12 +1097,33 @@ int main(int argc, char *argv[]) return 1; } + /* Note: test_shadow_stack_lock() needs write enabled */ if (ARCH_PRCTL(ARCH_SHSTK_ENABLE, ARCH_SHSTK_WRSS)) { printf("[SKIP]\tCould not enable WRSS\n"); ret = 1; goto out; } + unsigned long status = 0; + + if (ARCH_PRCTL(ARCH_SHSTK_STATUS, &status)) { + printf("[FAIL]\tCould not get Shadow stack status\n"); + ret = 1; + goto out; + } + + if (status != (ARCH_SHSTK_WRSS|ARCH_SHSTK_SHSTK)) { + printf("[FAIL]\tStatus not as expected, got 0x%lx status, wanted: 0x%llx\n", + status, (ARCH_SHSTK_WRSS|ARCH_SHSTK_SHSTK)); + ret = 1; + goto out; + } + + if (test_locking()) { + ret = 1; + goto out; + } + /* Should have succeeded if here, but this is a test, so double check. */ if (!get_ssp()) { printf("[FAIL]\tShadow stack disabled\n"); -- 2.55.0

