Home | History | Annotate | Download | only in src
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      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 "base/strings/stringprintf.h"
      6 #include "base/win/scoped_handle.h"
      7 
      8 #include "base/win/windows_version.h"
      9 #include "sandbox/win/src/nt_internals.h"
     10 #include "sandbox/win/src/process_mitigations.h"
     11 #include "sandbox/win/src/sandbox.h"
     12 #include "sandbox/win/src/sandbox_factory.h"
     13 #include "sandbox/win/src/sandbox_utils.h"
     14 #include "sandbox/win/src/target_services.h"
     15 #include "sandbox/win/src/win_utils.h"
     16 #include "sandbox/win/tests/common/controller.h"
     17 #include "testing/gtest/include/gtest/gtest.h"
     18 
     19 namespace {
     20 
     21 typedef BOOL (WINAPI *GetProcessDEPPolicyFunction)(
     22     HANDLE process,
     23     LPDWORD flags,
     24     PBOOL permanent);
     25 
     26 typedef BOOL (WINAPI *GetProcessMitigationPolicyFunction)(
     27     HANDLE process,
     28     PROCESS_MITIGATION_POLICY mitigation_policy,
     29     PVOID buffer,
     30     SIZE_T length);
     31 
     32 GetProcessMitigationPolicyFunction get_process_mitigation_policy;
     33 
     34 bool CheckWin8DepPolicy() {
     35   PROCESS_MITIGATION_DEP_POLICY policy;
     36   if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessDEPPolicy,
     37                                      &policy, sizeof(policy))) {
     38     return false;
     39   }
     40   return policy.Enable && policy.Permanent;
     41 }
     42 
     43 bool CheckWin8AslrPolicy() {
     44   PROCESS_MITIGATION_ASLR_POLICY policy;
     45   if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessASLRPolicy,
     46                                      &policy, sizeof(policy))) {
     47      return false;
     48   }
     49   return policy.EnableForceRelocateImages && policy.DisallowStrippedImages;
     50 }
     51 
     52 bool CheckWin8StrictHandlePolicy() {
     53   PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY policy;
     54   if (!get_process_mitigation_policy(::GetCurrentProcess(),
     55                                      ProcessStrictHandleCheckPolicy,
     56                                      &policy, sizeof(policy))) {
     57      return false;
     58   }
     59   return policy.RaiseExceptionOnInvalidHandleReference &&
     60          policy.HandleExceptionsPermanentlyEnabled;
     61 }
     62 
     63 bool CheckWin8Win32CallPolicy() {
     64   PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY policy;
     65   if (!get_process_mitigation_policy(::GetCurrentProcess(),
     66                                      ProcessSystemCallDisablePolicy,
     67                                      &policy, sizeof(policy))) {
     68      return false;
     69   }
     70   return policy.DisallowWin32kSystemCalls;
     71 }
     72 
     73 bool CheckWin8DllExtensionPolicy() {
     74   PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY policy;
     75   if (!get_process_mitigation_policy(::GetCurrentProcess(),
     76                                      ProcessExtensionPointDisablePolicy,
     77                                      &policy, sizeof(policy))) {
     78      return false;
     79   }
     80   return policy.DisableExtensionPoints;
     81 }
     82 
     83 }  // namespace
     84 
     85 namespace sandbox {
     86 
     87 SBOX_TESTS_COMMAND int CheckWin8(int argc, wchar_t **argv) {
     88   get_process_mitigation_policy =
     89       reinterpret_cast<GetProcessMitigationPolicyFunction>(
     90           ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"),
     91                            "GetProcessMitigationPolicy"));
     92 
     93   if (!get_process_mitigation_policy)
     94     return SBOX_TEST_NOT_FOUND;
     95 
     96   if (!CheckWin8DepPolicy())
     97     return SBOX_TEST_FIRST_ERROR;
     98 
     99 #if defined(NDEBUG)  // ASLR cannot be forced in debug builds.
    100   if (!CheckWin8AslrPolicy())
    101     return SBOX_TEST_SECOND_ERROR;
    102 #endif
    103 
    104   if (!CheckWin8StrictHandlePolicy())
    105     return SBOX_TEST_THIRD_ERROR;
    106 
    107   if (!CheckWin8Win32CallPolicy())
    108     return SBOX_TEST_FOURTH_ERROR;
    109 
    110   if (!CheckWin8DllExtensionPolicy())
    111     return SBOX_TEST_FIFTH_ERROR;
    112 
    113   return SBOX_TEST_SUCCEEDED;
    114 }
    115 
    116 TEST(ProcessMitigationsTest, CheckWin8) {
    117   if (base::win::GetVersion() < base::win::VERSION_WIN8)
    118     return;
    119 
    120   TestRunner runner;
    121   sandbox::TargetPolicy* policy = runner.GetPolicy();
    122 
    123   sandbox::MitigationFlags mitigations = MITIGATION_DEP |
    124                                          MITIGATION_DEP_NO_ATL_THUNK |
    125                                          MITIGATION_EXTENSION_DLL_DISABLE;
    126 #if defined(NDEBUG)  // ASLR cannot be forced in debug builds.
    127   mitigations |= MITIGATION_RELOCATE_IMAGE |
    128                  MITIGATION_RELOCATE_IMAGE_REQUIRED;
    129 #endif
    130 
    131   EXPECT_EQ(policy->SetProcessMitigations(mitigations), SBOX_ALL_OK);
    132 
    133   mitigations |= MITIGATION_STRICT_HANDLE_CHECKS |
    134                  MITIGATION_WIN32K_DISABLE;
    135 
    136   EXPECT_EQ(policy->SetDelayedProcessMitigations(mitigations), SBOX_ALL_OK);
    137 
    138   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8"));
    139 }
    140 
    141 
    142 SBOX_TESTS_COMMAND int CheckDep(int argc, wchar_t **argv) {
    143   GetProcessDEPPolicyFunction get_process_dep_policy =
    144       reinterpret_cast<GetProcessDEPPolicyFunction>(
    145           ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"),
    146                            "GetProcessDEPPolicy"));
    147   if (get_process_dep_policy) {
    148     BOOL is_permanent = FALSE;
    149     DWORD dep_flags = 0;
    150 
    151     if (!get_process_dep_policy(::GetCurrentProcess(), &dep_flags,
    152         &is_permanent)) {
    153       return SBOX_TEST_FIRST_ERROR;
    154     }
    155 
    156     if (!(dep_flags & PROCESS_DEP_ENABLE) || !is_permanent)
    157       return SBOX_TEST_SECOND_ERROR;
    158 
    159   } else {
    160     NtQueryInformationProcessFunction query_information_process = NULL;
    161     ResolveNTFunctionPtr("NtQueryInformationProcess",
    162                           &query_information_process);
    163     if (!query_information_process)
    164       return SBOX_TEST_NOT_FOUND;
    165 
    166     ULONG size = 0;
    167     ULONG dep_flags = 0;
    168     if (!SUCCEEDED(query_information_process(::GetCurrentProcess(),
    169                                              ProcessExecuteFlags, &dep_flags,
    170                                              sizeof(dep_flags), &size))) {
    171       return SBOX_TEST_THIRD_ERROR;
    172     }
    173 
    174     const int MEM_EXECUTE_OPTION_ENABLE = 1;
    175     const int MEM_EXECUTE_OPTION_DISABLE = 2;
    176     const int MEM_EXECUTE_OPTION_ATL7_THUNK_EMULATION = 4;
    177     const int MEM_EXECUTE_OPTION_PERMANENT = 8;
    178     dep_flags &= 0xff;
    179 
    180     if (dep_flags != (MEM_EXECUTE_OPTION_DISABLE |
    181                       MEM_EXECUTE_OPTION_PERMANENT)) {
    182       return SBOX_TEST_FOURTH_ERROR;
    183     }
    184   }
    185 
    186   return SBOX_TEST_SUCCEEDED;
    187 }
    188 
    189 #if !defined(_WIN64)  // DEP is always enabled on 64-bit.
    190 TEST(ProcessMitigationsTest, CheckDep) {
    191   if (!IsXPSP2OrLater() || base::win::GetVersion() > base::win::VERSION_WIN7)
    192     return;
    193 
    194   TestRunner runner;
    195   sandbox::TargetPolicy* policy = runner.GetPolicy();
    196 
    197   EXPECT_EQ(policy->SetProcessMitigations(
    198                 MITIGATION_DEP |
    199                 MITIGATION_DEP_NO_ATL_THUNK |
    200                 MITIGATION_SEHOP),
    201             SBOX_ALL_OK);
    202   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckDep"));
    203 }
    204 #endif
    205 
    206 }  // namespace sandbox
    207 
    208