Author | Tokens | Token Proportion | Commits | Commit Proportion |
---|---|---|---|---|
Mark Brown | 697 | 100.00% | 1 | 100.00% |
Total | 697 | 1 |
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2023 ARM Limited. * * Tests for GCS mode locking. These tests rely on both having GCS * unconfigured on entry and on the kselftest harness running each * test in a fork()ed process which will have it's own mode. */ #include <limits.h> #include <sys/auxv.h> #include <sys/prctl.h> #include <asm/hwcap.h> #include "kselftest_harness.h" #include "gcs-util.h" #define my_syscall2(num, arg1, arg2) \ ({ \ register long _num __asm__ ("x8") = (num); \ register long _arg1 __asm__ ("x0") = (long)(arg1); \ register long _arg2 __asm__ ("x1") = (long)(arg2); \ register long _arg3 __asm__ ("x2") = 0; \ register long _arg4 __asm__ ("x3") = 0; \ register long _arg5 __asm__ ("x4") = 0; \ \ __asm__ volatile ( \ "svc #0\n" \ : "=r"(_arg1) \ : "r"(_arg1), "r"(_arg2), \ "r"(_arg3), "r"(_arg4), \ "r"(_arg5), "r"(_num) \ : "memory", "cc" \ ); \ _arg1; \ }) /* No mode bits are rejected for locking */ TEST(lock_all_modes) { int ret; ret = prctl(PR_LOCK_SHADOW_STACK_STATUS, ULONG_MAX, 0, 0, 0); ASSERT_EQ(ret, 0); } FIXTURE(valid_modes) { }; FIXTURE_VARIANT(valid_modes) { unsigned long mode; }; FIXTURE_VARIANT_ADD(valid_modes, enable) { .mode = PR_SHADOW_STACK_ENABLE, }; FIXTURE_VARIANT_ADD(valid_modes, enable_write) { .mode = PR_SHADOW_STACK_ENABLE | PR_SHADOW_STACK_WRITE, }; FIXTURE_VARIANT_ADD(valid_modes, enable_push) { .mode = PR_SHADOW_STACK_ENABLE | PR_SHADOW_STACK_PUSH, }; FIXTURE_VARIANT_ADD(valid_modes, enable_write_push) { .mode = PR_SHADOW_STACK_ENABLE | PR_SHADOW_STACK_WRITE | PR_SHADOW_STACK_PUSH, }; FIXTURE_SETUP(valid_modes) { } FIXTURE_TEARDOWN(valid_modes) { } /* We can set the mode at all */ TEST_F(valid_modes, set) { int ret; ret = my_syscall2(__NR_prctl, PR_SET_SHADOW_STACK_STATUS, variant->mode); ASSERT_EQ(ret, 0); _exit(0); } /* Enabling, locking then disabling is rejected */ TEST_F(valid_modes, enable_lock_disable) { unsigned long mode; int ret; ret = my_syscall2(__NR_prctl, PR_SET_SHADOW_STACK_STATUS, variant->mode); ASSERT_EQ(ret, 0); ret = prctl(PR_GET_SHADOW_STACK_STATUS, &mode, 0, 0, 0); ASSERT_EQ(ret, 0); ASSERT_EQ(mode, variant->mode); ret = prctl(PR_LOCK_SHADOW_STACK_STATUS, variant->mode, 0, 0, 0); ASSERT_EQ(ret, 0); ret = my_syscall2(__NR_prctl, PR_SET_SHADOW_STACK_STATUS, 0); ASSERT_EQ(ret, -EBUSY); _exit(0); } /* Locking then enabling is rejected */ TEST_F(valid_modes, lock_enable) { unsigned long mode; int ret; ret = prctl(PR_LOCK_SHADOW_STACK_STATUS, variant->mode, 0, 0, 0); ASSERT_EQ(ret, 0); ret = my_syscall2(__NR_prctl, PR_SET_SHADOW_STACK_STATUS, variant->mode); ASSERT_EQ(ret, -EBUSY); ret = prctl(PR_GET_SHADOW_STACK_STATUS, &mode, 0, 0, 0); ASSERT_EQ(ret, 0); ASSERT_EQ(mode, 0); _exit(0); } /* Locking then changing other modes is fine */ TEST_F(valid_modes, lock_enable_disable_others) { unsigned long mode; int ret; ret = my_syscall2(__NR_prctl, PR_SET_SHADOW_STACK_STATUS, variant->mode); ASSERT_EQ(ret, 0); ret = prctl(PR_GET_SHADOW_STACK_STATUS, &mode, 0, 0, 0); ASSERT_EQ(ret, 0); ASSERT_EQ(mode, variant->mode); ret = prctl(PR_LOCK_SHADOW_STACK_STATUS, variant->mode, 0, 0, 0); ASSERT_EQ(ret, 0); ret = my_syscall2(__NR_prctl, PR_SET_SHADOW_STACK_STATUS, PR_SHADOW_STACK_ALL_MODES); ASSERT_EQ(ret, 0); ret = prctl(PR_GET_SHADOW_STACK_STATUS, &mode, 0, 0, 0); ASSERT_EQ(ret, 0); ASSERT_EQ(mode, PR_SHADOW_STACK_ALL_MODES); ret = my_syscall2(__NR_prctl, PR_SET_SHADOW_STACK_STATUS, variant->mode); ASSERT_EQ(ret, 0); ret = prctl(PR_GET_SHADOW_STACK_STATUS, &mode, 0, 0, 0); ASSERT_EQ(ret, 0); ASSERT_EQ(mode, variant->mode); _exit(0); } int main(int argc, char **argv) { unsigned long mode; int ret; if (!(getauxval(AT_HWCAP) & HWCAP_GCS)) ksft_exit_skip("SKIP GCS not supported\n"); ret = prctl(PR_GET_SHADOW_STACK_STATUS, &mode, 0, 0, 0); if (ret) { ksft_print_msg("Failed to read GCS state: %d\n", ret); return EXIT_FAILURE; } if (mode & PR_SHADOW_STACK_ENABLE) { ksft_print_msg("GCS was enabled, test unsupported\n"); return KSFT_SKIP; } return test_harness_run(argc, argv); }
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with Cregit http://github.com/cregit/cregit
Version 2.0-RC1