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.
---
.../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