security/sandbox/win/src/process_thread_policy.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
michael@0 2 // Use of this source code is governed by a BSD-style license that can be
michael@0 3 // found in the LICENSE file.
michael@0 4
michael@0 5 #include "sandbox/win/src/process_thread_policy.h"
michael@0 6
michael@0 7 #include <string>
michael@0 8
michael@0 9 #include "base/memory/scoped_ptr.h"
michael@0 10 #include "sandbox/win/src/ipc_tags.h"
michael@0 11 #include "sandbox/win/src/nt_internals.h"
michael@0 12 #include "sandbox/win/src/policy_engine_opcodes.h"
michael@0 13 #include "sandbox/win/src/policy_params.h"
michael@0 14 #include "sandbox/win/src/sandbox_types.h"
michael@0 15 #include "sandbox/win/src/win_utils.h"
michael@0 16
michael@0 17 namespace {
michael@0 18
michael@0 19 // These are the only safe rights that can be given to a sandboxed
michael@0 20 // process for the process created by the broker. All others are potential
michael@0 21 // vectors of privilege elevation.
michael@0 22 const DWORD kProcessRights = SYNCHRONIZE |
michael@0 23 PROCESS_QUERY_INFORMATION |
michael@0 24 PROCESS_QUERY_LIMITED_INFORMATION |
michael@0 25 PROCESS_TERMINATE |
michael@0 26 PROCESS_SUSPEND_RESUME;
michael@0 27
michael@0 28 const DWORD kThreadRights = SYNCHRONIZE |
michael@0 29 THREAD_TERMINATE |
michael@0 30 THREAD_SUSPEND_RESUME |
michael@0 31 THREAD_QUERY_INFORMATION |
michael@0 32 THREAD_QUERY_LIMITED_INFORMATION |
michael@0 33 THREAD_SET_LIMITED_INFORMATION;
michael@0 34
michael@0 35 // Creates a child process and duplicates the handles to 'target_process'. The
michael@0 36 // remaining parameters are the same as CreateProcess().
michael@0 37 BOOL CreateProcessExWHelper(HANDLE target_process, BOOL give_full_access,
michael@0 38 LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
michael@0 39 LPSECURITY_ATTRIBUTES lpProcessAttributes,
michael@0 40 LPSECURITY_ATTRIBUTES lpThreadAttributes,
michael@0 41 BOOL bInheritHandles, DWORD dwCreationFlags,
michael@0 42 LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory,
michael@0 43 LPSTARTUPINFOW lpStartupInfo,
michael@0 44 LPPROCESS_INFORMATION lpProcessInformation) {
michael@0 45 if (!::CreateProcessW(lpApplicationName, lpCommandLine, lpProcessAttributes,
michael@0 46 lpThreadAttributes, bInheritHandles, dwCreationFlags,
michael@0 47 lpEnvironment, lpCurrentDirectory, lpStartupInfo,
michael@0 48 lpProcessInformation)) {
michael@0 49 return FALSE;
michael@0 50 }
michael@0 51
michael@0 52 DWORD process_access = kProcessRights;
michael@0 53 DWORD thread_access = kThreadRights;
michael@0 54 if (give_full_access) {
michael@0 55 process_access = PROCESS_ALL_ACCESS;
michael@0 56 thread_access = THREAD_ALL_ACCESS;
michael@0 57 }
michael@0 58 if (!::DuplicateHandle(::GetCurrentProcess(), lpProcessInformation->hProcess,
michael@0 59 target_process, &lpProcessInformation->hProcess,
michael@0 60 process_access, FALSE, DUPLICATE_CLOSE_SOURCE)) {
michael@0 61 ::CloseHandle(lpProcessInformation->hThread);
michael@0 62 return FALSE;
michael@0 63 }
michael@0 64 if (!::DuplicateHandle(::GetCurrentProcess(), lpProcessInformation->hThread,
michael@0 65 target_process, &lpProcessInformation->hThread,
michael@0 66 thread_access, FALSE, DUPLICATE_CLOSE_SOURCE)) {
michael@0 67 return FALSE;
michael@0 68 }
michael@0 69 return TRUE;
michael@0 70 }
michael@0 71
michael@0 72 }
michael@0 73
michael@0 74 namespace sandbox {
michael@0 75
michael@0 76 bool ProcessPolicy::GenerateRules(const wchar_t* name,
michael@0 77 TargetPolicy::Semantics semantics,
michael@0 78 LowLevelPolicy* policy) {
michael@0 79 scoped_ptr<PolicyRule> process;
michael@0 80 switch (semantics) {
michael@0 81 case TargetPolicy::PROCESS_MIN_EXEC: {
michael@0 82 process.reset(new PolicyRule(GIVE_READONLY));
michael@0 83 break;
michael@0 84 };
michael@0 85 case TargetPolicy::PROCESS_ALL_EXEC: {
michael@0 86 process.reset(new PolicyRule(GIVE_ALLACCESS));
michael@0 87 break;
michael@0 88 };
michael@0 89 default: {
michael@0 90 return false;
michael@0 91 };
michael@0 92 }
michael@0 93
michael@0 94 if (!process->AddStringMatch(IF, NameBased::NAME, name, CASE_INSENSITIVE)) {
michael@0 95 return false;
michael@0 96 }
michael@0 97 if (!policy->AddRule(IPC_CREATEPROCESSW_TAG, process.get())) {
michael@0 98 return false;
michael@0 99 }
michael@0 100 return true;
michael@0 101 }
michael@0 102
michael@0 103 NTSTATUS ProcessPolicy::OpenThreadAction(const ClientInfo& client_info,
michael@0 104 uint32 desired_access,
michael@0 105 uint32 thread_id,
michael@0 106 HANDLE* handle) {
michael@0 107 *handle = NULL;
michael@0 108
michael@0 109 NtOpenThreadFunction NtOpenThread = NULL;
michael@0 110 ResolveNTFunctionPtr("NtOpenThread", &NtOpenThread);
michael@0 111
michael@0 112 OBJECT_ATTRIBUTES attributes = {0};
michael@0 113 attributes.Length = sizeof(attributes);
michael@0 114 CLIENT_ID client_id = {0};
michael@0 115 client_id.UniqueProcess = reinterpret_cast<PVOID>(
michael@0 116 static_cast<ULONG_PTR>(client_info.process_id));
michael@0 117 client_id.UniqueThread =
michael@0 118 reinterpret_cast<PVOID>(static_cast<ULONG_PTR>(thread_id));
michael@0 119
michael@0 120 HANDLE local_handle;
michael@0 121 NTSTATUS status = NtOpenThread(&local_handle, desired_access, &attributes,
michael@0 122 &client_id);
michael@0 123 if (NT_SUCCESS(status)) {
michael@0 124 if (!::DuplicateHandle(::GetCurrentProcess(), local_handle,
michael@0 125 client_info.process, handle, 0, FALSE,
michael@0 126 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
michael@0 127 ::CloseHandle(local_handle);
michael@0 128 return STATUS_ACCESS_DENIED;
michael@0 129 }
michael@0 130 }
michael@0 131
michael@0 132 return status;
michael@0 133 }
michael@0 134
michael@0 135 NTSTATUS ProcessPolicy::OpenProcessAction(const ClientInfo& client_info,
michael@0 136 uint32 desired_access,
michael@0 137 uint32 process_id,
michael@0 138 HANDLE* handle) {
michael@0 139 *handle = NULL;
michael@0 140
michael@0 141 NtOpenProcessFunction NtOpenProcess = NULL;
michael@0 142 ResolveNTFunctionPtr("NtOpenProcess", &NtOpenProcess);
michael@0 143
michael@0 144 if (client_info.process_id != process_id)
michael@0 145 return STATUS_ACCESS_DENIED;
michael@0 146
michael@0 147 OBJECT_ATTRIBUTES attributes = {0};
michael@0 148 attributes.Length = sizeof(attributes);
michael@0 149 CLIENT_ID client_id = {0};
michael@0 150 client_id.UniqueProcess = reinterpret_cast<PVOID>(
michael@0 151 static_cast<ULONG_PTR>(client_info.process_id));
michael@0 152 HANDLE local_handle;
michael@0 153 NTSTATUS status = NtOpenProcess(&local_handle, desired_access, &attributes,
michael@0 154 &client_id);
michael@0 155 if (NT_SUCCESS(status)) {
michael@0 156 if (!::DuplicateHandle(::GetCurrentProcess(), local_handle,
michael@0 157 client_info.process, handle, 0, FALSE,
michael@0 158 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
michael@0 159 ::CloseHandle(local_handle);
michael@0 160 return STATUS_ACCESS_DENIED;
michael@0 161 }
michael@0 162 }
michael@0 163
michael@0 164 return status;
michael@0 165 }
michael@0 166
michael@0 167 NTSTATUS ProcessPolicy::OpenProcessTokenAction(const ClientInfo& client_info,
michael@0 168 HANDLE process,
michael@0 169 uint32 desired_access,
michael@0 170 HANDLE* handle) {
michael@0 171 *handle = NULL;
michael@0 172 NtOpenProcessTokenFunction NtOpenProcessToken = NULL;
michael@0 173 ResolveNTFunctionPtr("NtOpenProcessToken", &NtOpenProcessToken);
michael@0 174
michael@0 175 if (CURRENT_PROCESS != process)
michael@0 176 return STATUS_ACCESS_DENIED;
michael@0 177
michael@0 178 HANDLE local_handle;
michael@0 179 NTSTATUS status = NtOpenProcessToken(client_info.process, desired_access,
michael@0 180 &local_handle);
michael@0 181 if (NT_SUCCESS(status)) {
michael@0 182 if (!::DuplicateHandle(::GetCurrentProcess(), local_handle,
michael@0 183 client_info.process, handle, 0, FALSE,
michael@0 184 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
michael@0 185 ::CloseHandle(local_handle);
michael@0 186 return STATUS_ACCESS_DENIED;
michael@0 187 }
michael@0 188 }
michael@0 189 return status;
michael@0 190 }
michael@0 191
michael@0 192 NTSTATUS ProcessPolicy::OpenProcessTokenExAction(const ClientInfo& client_info,
michael@0 193 HANDLE process,
michael@0 194 uint32 desired_access,
michael@0 195 uint32 attributes,
michael@0 196 HANDLE* handle) {
michael@0 197 *handle = NULL;
michael@0 198 NtOpenProcessTokenExFunction NtOpenProcessTokenEx = NULL;
michael@0 199 ResolveNTFunctionPtr("NtOpenProcessTokenEx", &NtOpenProcessTokenEx);
michael@0 200
michael@0 201 if (CURRENT_PROCESS != process)
michael@0 202 return STATUS_ACCESS_DENIED;
michael@0 203
michael@0 204 HANDLE local_handle;
michael@0 205 NTSTATUS status = NtOpenProcessTokenEx(client_info.process, desired_access,
michael@0 206 attributes, &local_handle);
michael@0 207 if (NT_SUCCESS(status)) {
michael@0 208 if (!::DuplicateHandle(::GetCurrentProcess(), local_handle,
michael@0 209 client_info.process, handle, 0, FALSE,
michael@0 210 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
michael@0 211 ::CloseHandle(local_handle);
michael@0 212 return STATUS_ACCESS_DENIED;
michael@0 213 }
michael@0 214 }
michael@0 215 return status;
michael@0 216 }
michael@0 217
michael@0 218 DWORD ProcessPolicy::CreateProcessWAction(EvalResult eval_result,
michael@0 219 const ClientInfo& client_info,
michael@0 220 const std::wstring &app_name,
michael@0 221 const std::wstring &command_line,
michael@0 222 PROCESS_INFORMATION* process_info) {
michael@0 223 // The only action supported is ASK_BROKER which means create the process.
michael@0 224 if (GIVE_ALLACCESS != eval_result && GIVE_READONLY != eval_result) {
michael@0 225 return ERROR_ACCESS_DENIED;
michael@0 226 }
michael@0 227
michael@0 228 STARTUPINFO startup_info = {0};
michael@0 229 startup_info.cb = sizeof(startup_info);
michael@0 230 scoped_ptr_malloc<wchar_t> cmd_line(_wcsdup(command_line.c_str()));
michael@0 231
michael@0 232 BOOL should_give_full_access = (GIVE_ALLACCESS == eval_result);
michael@0 233 if (!CreateProcessExWHelper(client_info.process, should_give_full_access,
michael@0 234 app_name.c_str(), cmd_line.get(), NULL, NULL,
michael@0 235 FALSE, 0, NULL, NULL, &startup_info,
michael@0 236 process_info)) {
michael@0 237 return ERROR_ACCESS_DENIED;
michael@0 238 }
michael@0 239 return ERROR_SUCCESS;
michael@0 240 }
michael@0 241
michael@0 242 } // namespace sandbox

mercurial