1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/sandbox/win/src/registry_dispatcher.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,161 @@ 1.4 +// Copyright (c) 2011 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#include "sandbox/win/src/registry_dispatcher.h" 1.9 + 1.10 +#include "base/win/scoped_handle.h" 1.11 +#include "base/win/windows_version.h" 1.12 +#include "sandbox/win/src/crosscall_client.h" 1.13 +#include "sandbox/win/src/interception.h" 1.14 +#include "sandbox/win/src/interceptors.h" 1.15 +#include "sandbox/win/src/ipc_tags.h" 1.16 +#include "sandbox/win/src/sandbox_nt_util.h" 1.17 +#include "sandbox/win/src/policy_broker.h" 1.18 +#include "sandbox/win/src/policy_params.h" 1.19 +#include "sandbox/win/src/sandbox.h" 1.20 +#include "sandbox/win/src/registry_interception.h" 1.21 +#include "sandbox/win/src/registry_policy.h" 1.22 + 1.23 +namespace { 1.24 + 1.25 +// Builds a path using the root directory and the name. 1.26 +bool GetCompletePath(HANDLE root, const std::wstring& name, 1.27 + std::wstring* complete_name) { 1.28 + if (root) { 1.29 + if (!sandbox::GetPathFromHandle(root, complete_name)) 1.30 + return false; 1.31 + 1.32 + *complete_name += L"\\"; 1.33 + *complete_name += name; 1.34 + } else { 1.35 + *complete_name = name; 1.36 + } 1.37 + 1.38 + return true; 1.39 +} 1.40 + 1.41 +} 1.42 + 1.43 +namespace sandbox { 1.44 + 1.45 +RegistryDispatcher::RegistryDispatcher(PolicyBase* policy_base) 1.46 + : policy_base_(policy_base) { 1.47 + static const IPCCall create_params = { 1.48 + {IPC_NTCREATEKEY_TAG, WCHAR_TYPE, ULONG_TYPE, VOIDPTR_TYPE, ULONG_TYPE, 1.49 + ULONG_TYPE, ULONG_TYPE}, 1.50 + reinterpret_cast<CallbackGeneric>(&RegistryDispatcher::NtCreateKey) 1.51 + }; 1.52 + 1.53 + static const IPCCall open_params = { 1.54 + {IPC_NTOPENKEY_TAG, WCHAR_TYPE, ULONG_TYPE, VOIDPTR_TYPE, ULONG_TYPE}, 1.55 + reinterpret_cast<CallbackGeneric>(&RegistryDispatcher::NtOpenKey) 1.56 + }; 1.57 + 1.58 + ipc_calls_.push_back(create_params); 1.59 + ipc_calls_.push_back(open_params); 1.60 +} 1.61 + 1.62 +bool RegistryDispatcher::SetupService(InterceptionManager* manager, 1.63 + int service) { 1.64 + if (IPC_NTCREATEKEY_TAG == service) 1.65 + return INTERCEPT_NT(manager, NtCreateKey, CREATE_KEY_ID, 32); 1.66 + 1.67 + if (IPC_NTOPENKEY_TAG == service) { 1.68 + bool result = INTERCEPT_NT(manager, NtOpenKey, OPEN_KEY_ID, 16); 1.69 + if (base::win::GetVersion() >= base::win::VERSION_WIN7) 1.70 + result &= INTERCEPT_NT(manager, NtOpenKeyEx, OPEN_KEY_EX_ID, 20); 1.71 + return result; 1.72 + } 1.73 + 1.74 + return false; 1.75 +} 1.76 + 1.77 +bool RegistryDispatcher::NtCreateKey( 1.78 + IPCInfo* ipc, std::wstring* name, DWORD attributes, HANDLE root, 1.79 + DWORD desired_access, DWORD title_index, DWORD create_options) { 1.80 + base::win::ScopedHandle root_handle; 1.81 + std::wstring real_path = *name; 1.82 + 1.83 + // If there is a root directory, we need to duplicate the handle to make 1.84 + // it valid in this process. 1.85 + if (root) { 1.86 + if (!::DuplicateHandle(ipc->client_info->process, root, 1.87 + ::GetCurrentProcess(), &root, 0, FALSE, 1.88 + DUPLICATE_SAME_ACCESS)) 1.89 + return false; 1.90 + 1.91 + root_handle.Set(root); 1.92 + } 1.93 + 1.94 + if (!GetCompletePath(root, *name, &real_path)) 1.95 + return false; 1.96 + 1.97 + const wchar_t* regname = real_path.c_str(); 1.98 + CountedParameterSet<OpenKey> params; 1.99 + params[OpenKey::NAME] = ParamPickerMake(regname); 1.100 + params[OpenKey::ACCESS] = ParamPickerMake(desired_access); 1.101 + 1.102 + EvalResult result = policy_base_->EvalPolicy(IPC_NTCREATEKEY_TAG, 1.103 + params.GetBase()); 1.104 + 1.105 + HANDLE handle; 1.106 + NTSTATUS nt_status; 1.107 + ULONG disposition = 0; 1.108 + if (!RegistryPolicy::CreateKeyAction(result, *ipc->client_info, *name, 1.109 + attributes, root, desired_access, 1.110 + title_index, create_options, &handle, 1.111 + &nt_status, &disposition)) { 1.112 + ipc->return_info.nt_status = STATUS_ACCESS_DENIED; 1.113 + return true; 1.114 + } 1.115 + 1.116 + // Return operation status on the IPC. 1.117 + ipc->return_info.extended[0].unsigned_int = disposition; 1.118 + ipc->return_info.nt_status = nt_status; 1.119 + ipc->return_info.handle = handle; 1.120 + return true; 1.121 +} 1.122 + 1.123 +bool RegistryDispatcher::NtOpenKey(IPCInfo* ipc, std::wstring* name, 1.124 + DWORD attributes, HANDLE root, 1.125 + DWORD desired_access) { 1.126 + base::win::ScopedHandle root_handle; 1.127 + std::wstring real_path = *name; 1.128 + 1.129 + // If there is a root directory, we need to duplicate the handle to make 1.130 + // it valid in this process. 1.131 + if (root) { 1.132 + if (!::DuplicateHandle(ipc->client_info->process, root, 1.133 + ::GetCurrentProcess(), &root, 0, FALSE, 1.134 + DUPLICATE_SAME_ACCESS)) 1.135 + return false; 1.136 + root_handle.Set(root); 1.137 + } 1.138 + 1.139 + if (!GetCompletePath(root, *name, &real_path)) 1.140 + return false; 1.141 + 1.142 + const wchar_t* regname = real_path.c_str(); 1.143 + CountedParameterSet<OpenKey> params; 1.144 + params[OpenKey::NAME] = ParamPickerMake(regname); 1.145 + params[OpenKey::ACCESS] = ParamPickerMake(desired_access); 1.146 + 1.147 + EvalResult result = policy_base_->EvalPolicy(IPC_NTOPENKEY_TAG, 1.148 + params.GetBase()); 1.149 + HANDLE handle; 1.150 + NTSTATUS nt_status; 1.151 + if (!RegistryPolicy::OpenKeyAction(result, *ipc->client_info, *name, 1.152 + attributes, root, desired_access, &handle, 1.153 + &nt_status)) { 1.154 + ipc->return_info.nt_status = STATUS_ACCESS_DENIED; 1.155 + return true; 1.156 + } 1.157 + 1.158 + // Return operation status on the IPC. 1.159 + ipc->return_info.nt_status = nt_status; 1.160 + ipc->return_info.handle = handle; 1.161 + return true; 1.162 +} 1.163 + 1.164 +} // namespace sandbox