1 // Copyright 2020 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <Windows.h> 6 #include <intrin.h> 7 8 #include "base/compiler_specific.h" 9 #include "base/win/windows_version.h" 10 #include "testing/gtest/include/gtest/gtest.h" 11 12 namespace base { 13 namespace win { 14 15 namespace { 16 IsHardwareEnforcedShadowStacksEnabled()17bool IsHardwareEnforcedShadowStacksEnabled() { 18 // Only supported post Win 10 2004. 19 if (base::win::GetVersion() < base::win::Version::WIN10_20H1) 20 return false; 21 22 PROCESS_MITIGATION_USER_SHADOW_STACK_POLICY uss_policy; 23 if (!::GetProcessMitigationPolicy(GetCurrentProcess(), 24 ProcessUserShadowStackPolicy, &uss_policy, 25 sizeof(uss_policy))) { 26 return false; 27 } 28 29 if (uss_policy.EnableUserShadowStack) 30 return true; 31 else 32 return false; 33 } 34 35 void* return_address; 36 37 // Bug() simulates a ROP. The first time we are called we save the 38 // address we will return to and return to it (like a normal function 39 // call). The second time we return to the saved address. If called 40 // from a different function the second time, this redirects control 41 // flow and should be different from the return address in the shadow 42 // stack. Bug()43NOINLINE void Bug() { 44 void* pvAddressOfReturnAddress = _AddressOfReturnAddress(); 45 if (!return_address) 46 return_address = *reinterpret_cast<void**>(pvAddressOfReturnAddress); 47 else 48 *reinterpret_cast<void**>(pvAddressOfReturnAddress) = return_address; 49 } 50 A()51NOINLINE void A() { 52 Bug(); 53 } 54 B()55NOINLINE void B() { 56 Bug(); 57 } 58 59 } // namespace 60 TEST(CET,ShadowStack)61TEST(CET, ShadowStack) { 62 if (IsHardwareEnforcedShadowStacksEnabled()) { 63 A(); 64 EXPECT_DEATH(B(), ""); 65 } 66 } 67 68 } // namespace win 69 } // namespace base 70