xref: /aosp_15_r20/external/cronet/base/win/cet_shadow_stack_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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()17 bool 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()43 NOINLINE 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()51 NOINLINE void A() {
52   Bug();
53 }
54 
B()55 NOINLINE void B() {
56   Bug();
57 }
58 
59 }  // namespace
60 
TEST(CET,ShadowStack)61 TEST(CET, ShadowStack) {
62   if (IsHardwareEnforcedShadowStacksEnabled()) {
63     A();
64     EXPECT_DEATH(B(), "");
65   }
66 }
67 
68 }  // namespace win
69 }  // namespace base
70