Wed, 31 Dec 2014 06:09:35 +0100
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) 2006-2008 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/filesystem_interception.h" |
michael@0 | 6 | |
michael@0 | 7 | #include "sandbox/win/src/crosscall_client.h" |
michael@0 | 8 | #include "sandbox/win/src/ipc_tags.h" |
michael@0 | 9 | #include "sandbox/win/src/policy_params.h" |
michael@0 | 10 | #include "sandbox/win/src/policy_target.h" |
michael@0 | 11 | #include "sandbox/win/src/sandbox_factory.h" |
michael@0 | 12 | #include "sandbox/win/src/sandbox_nt_util.h" |
michael@0 | 13 | #include "sandbox/win/src/sharedmem_ipc_client.h" |
michael@0 | 14 | #include "sandbox/win/src/target_services.h" |
michael@0 | 15 | |
michael@0 | 16 | namespace sandbox { |
michael@0 | 17 | |
michael@0 | 18 | NTSTATUS WINAPI TargetNtCreateFile(NtCreateFileFunction orig_CreateFile, |
michael@0 | 19 | PHANDLE file, ACCESS_MASK desired_access, |
michael@0 | 20 | POBJECT_ATTRIBUTES object_attributes, |
michael@0 | 21 | PIO_STATUS_BLOCK io_status, |
michael@0 | 22 | PLARGE_INTEGER allocation_size, |
michael@0 | 23 | ULONG file_attributes, ULONG sharing, |
michael@0 | 24 | ULONG disposition, ULONG options, |
michael@0 | 25 | PVOID ea_buffer, ULONG ea_length) { |
michael@0 | 26 | // Check if the process can open it first. |
michael@0 | 27 | NTSTATUS status = orig_CreateFile(file, desired_access, object_attributes, |
michael@0 | 28 | io_status, allocation_size, |
michael@0 | 29 | file_attributes, sharing, disposition, |
michael@0 | 30 | options, ea_buffer, ea_length); |
michael@0 | 31 | if (STATUS_ACCESS_DENIED != status) |
michael@0 | 32 | return status; |
michael@0 | 33 | |
michael@0 | 34 | // We don't trust that the IPC can work this early. |
michael@0 | 35 | if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) |
michael@0 | 36 | return status; |
michael@0 | 37 | |
michael@0 | 38 | do { |
michael@0 | 39 | if (!ValidParameter(file, sizeof(HANDLE), WRITE)) |
michael@0 | 40 | break; |
michael@0 | 41 | if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE)) |
michael@0 | 42 | break; |
michael@0 | 43 | |
michael@0 | 44 | void* memory = GetGlobalIPCMemory(); |
michael@0 | 45 | if (NULL == memory) |
michael@0 | 46 | break; |
michael@0 | 47 | |
michael@0 | 48 | wchar_t* name; |
michael@0 | 49 | uint32 attributes = 0; |
michael@0 | 50 | NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes, |
michael@0 | 51 | NULL); |
michael@0 | 52 | if (!NT_SUCCESS(ret) || NULL == name) |
michael@0 | 53 | break; |
michael@0 | 54 | |
michael@0 | 55 | ULONG broker = FALSE; |
michael@0 | 56 | CountedParameterSet<OpenFile> params; |
michael@0 | 57 | params[OpenFile::NAME] = ParamPickerMake(name); |
michael@0 | 58 | params[OpenFile::ACCESS] = ParamPickerMake(desired_access); |
michael@0 | 59 | params[OpenFile::OPTIONS] = ParamPickerMake(options); |
michael@0 | 60 | params[OpenFile::BROKER] = ParamPickerMake(broker); |
michael@0 | 61 | |
michael@0 | 62 | if (!QueryBroker(IPC_NTCREATEFILE_TAG, params.GetBase())) |
michael@0 | 63 | break; |
michael@0 | 64 | |
michael@0 | 65 | SharedMemIPCClient ipc(memory); |
michael@0 | 66 | CrossCallReturn answer = {0}; |
michael@0 | 67 | // The following call must match in the parameters with |
michael@0 | 68 | // FilesystemDispatcher::ProcessNtCreateFile. |
michael@0 | 69 | ResultCode code = CrossCall(ipc, IPC_NTCREATEFILE_TAG, name, attributes, |
michael@0 | 70 | desired_access, file_attributes, sharing, |
michael@0 | 71 | disposition, options, &answer); |
michael@0 | 72 | |
michael@0 | 73 | operator delete(name, NT_ALLOC); |
michael@0 | 74 | |
michael@0 | 75 | if (SBOX_ALL_OK != code) |
michael@0 | 76 | break; |
michael@0 | 77 | |
michael@0 | 78 | if (!NT_SUCCESS(answer.nt_status)) |
michael@0 | 79 | return answer.nt_status; |
michael@0 | 80 | |
michael@0 | 81 | __try { |
michael@0 | 82 | *file = answer.handle; |
michael@0 | 83 | io_status->Status = answer.nt_status; |
michael@0 | 84 | io_status->Information = answer.extended[0].ulong_ptr; |
michael@0 | 85 | status = io_status->Status; |
michael@0 | 86 | } __except(EXCEPTION_EXECUTE_HANDLER) { |
michael@0 | 87 | break; |
michael@0 | 88 | } |
michael@0 | 89 | } while (false); |
michael@0 | 90 | |
michael@0 | 91 | return status; |
michael@0 | 92 | } |
michael@0 | 93 | |
michael@0 | 94 | NTSTATUS WINAPI TargetNtOpenFile(NtOpenFileFunction orig_OpenFile, PHANDLE file, |
michael@0 | 95 | ACCESS_MASK desired_access, |
michael@0 | 96 | POBJECT_ATTRIBUTES object_attributes, |
michael@0 | 97 | PIO_STATUS_BLOCK io_status, ULONG sharing, |
michael@0 | 98 | ULONG options) { |
michael@0 | 99 | // Check if the process can open it first. |
michael@0 | 100 | NTSTATUS status = orig_OpenFile(file, desired_access, object_attributes, |
michael@0 | 101 | io_status, sharing, options); |
michael@0 | 102 | if (STATUS_ACCESS_DENIED != status) |
michael@0 | 103 | return status; |
michael@0 | 104 | |
michael@0 | 105 | // We don't trust that the IPC can work this early. |
michael@0 | 106 | if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) |
michael@0 | 107 | return status; |
michael@0 | 108 | |
michael@0 | 109 | do { |
michael@0 | 110 | if (!ValidParameter(file, sizeof(HANDLE), WRITE)) |
michael@0 | 111 | break; |
michael@0 | 112 | if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE)) |
michael@0 | 113 | break; |
michael@0 | 114 | |
michael@0 | 115 | void* memory = GetGlobalIPCMemory(); |
michael@0 | 116 | if (NULL == memory) |
michael@0 | 117 | break; |
michael@0 | 118 | |
michael@0 | 119 | wchar_t* name; |
michael@0 | 120 | uint32 attributes; |
michael@0 | 121 | NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes, |
michael@0 | 122 | NULL); |
michael@0 | 123 | if (!NT_SUCCESS(ret) || NULL == name) |
michael@0 | 124 | break; |
michael@0 | 125 | |
michael@0 | 126 | ULONG broker = FALSE; |
michael@0 | 127 | CountedParameterSet<OpenFile> params; |
michael@0 | 128 | params[OpenFile::NAME] = ParamPickerMake(name); |
michael@0 | 129 | params[OpenFile::ACCESS] = ParamPickerMake(desired_access); |
michael@0 | 130 | params[OpenFile::OPTIONS] = ParamPickerMake(options); |
michael@0 | 131 | params[OpenFile::BROKER] = ParamPickerMake(broker); |
michael@0 | 132 | |
michael@0 | 133 | if (!QueryBroker(IPC_NTOPENFILE_TAG, params.GetBase())) |
michael@0 | 134 | break; |
michael@0 | 135 | |
michael@0 | 136 | SharedMemIPCClient ipc(memory); |
michael@0 | 137 | CrossCallReturn answer = {0}; |
michael@0 | 138 | ResultCode code = CrossCall(ipc, IPC_NTOPENFILE_TAG, name, attributes, |
michael@0 | 139 | desired_access, sharing, options, &answer); |
michael@0 | 140 | |
michael@0 | 141 | operator delete(name, NT_ALLOC); |
michael@0 | 142 | |
michael@0 | 143 | if (SBOX_ALL_OK != code) |
michael@0 | 144 | break; |
michael@0 | 145 | |
michael@0 | 146 | if (!NT_SUCCESS(answer.nt_status)) |
michael@0 | 147 | return answer.nt_status; |
michael@0 | 148 | |
michael@0 | 149 | __try { |
michael@0 | 150 | *file = answer.handle; |
michael@0 | 151 | io_status->Status = answer.nt_status; |
michael@0 | 152 | io_status->Information = answer.extended[0].ulong_ptr; |
michael@0 | 153 | status = io_status->Status; |
michael@0 | 154 | } __except(EXCEPTION_EXECUTE_HANDLER) { |
michael@0 | 155 | break; |
michael@0 | 156 | } |
michael@0 | 157 | } while (false); |
michael@0 | 158 | |
michael@0 | 159 | return status; |
michael@0 | 160 | } |
michael@0 | 161 | |
michael@0 | 162 | NTSTATUS WINAPI TargetNtQueryAttributesFile( |
michael@0 | 163 | NtQueryAttributesFileFunction orig_QueryAttributes, |
michael@0 | 164 | POBJECT_ATTRIBUTES object_attributes, |
michael@0 | 165 | PFILE_BASIC_INFORMATION file_attributes) { |
michael@0 | 166 | // Check if the process can query it first. |
michael@0 | 167 | NTSTATUS status = orig_QueryAttributes(object_attributes, file_attributes); |
michael@0 | 168 | if (STATUS_ACCESS_DENIED != status) |
michael@0 | 169 | return status; |
michael@0 | 170 | |
michael@0 | 171 | // We don't trust that the IPC can work this early. |
michael@0 | 172 | if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) |
michael@0 | 173 | return status; |
michael@0 | 174 | |
michael@0 | 175 | do { |
michael@0 | 176 | if (!ValidParameter(file_attributes, sizeof(FILE_BASIC_INFORMATION), WRITE)) |
michael@0 | 177 | break; |
michael@0 | 178 | |
michael@0 | 179 | void* memory = GetGlobalIPCMemory(); |
michael@0 | 180 | if (NULL == memory) |
michael@0 | 181 | break; |
michael@0 | 182 | |
michael@0 | 183 | wchar_t* name = NULL; |
michael@0 | 184 | uint32 attributes = 0; |
michael@0 | 185 | NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes, |
michael@0 | 186 | NULL); |
michael@0 | 187 | if (!NT_SUCCESS(ret) || NULL == name) |
michael@0 | 188 | break; |
michael@0 | 189 | |
michael@0 | 190 | InOutCountedBuffer file_info(file_attributes, |
michael@0 | 191 | sizeof(FILE_BASIC_INFORMATION)); |
michael@0 | 192 | |
michael@0 | 193 | ULONG broker = FALSE; |
michael@0 | 194 | CountedParameterSet<FileName> params; |
michael@0 | 195 | params[FileName::NAME] = ParamPickerMake(name); |
michael@0 | 196 | params[FileName::BROKER] = ParamPickerMake(broker); |
michael@0 | 197 | |
michael@0 | 198 | if (!QueryBroker(IPC_NTQUERYATTRIBUTESFILE_TAG, params.GetBase())) |
michael@0 | 199 | break; |
michael@0 | 200 | |
michael@0 | 201 | SharedMemIPCClient ipc(memory); |
michael@0 | 202 | CrossCallReturn answer = {0}; |
michael@0 | 203 | ResultCode code = CrossCall(ipc, IPC_NTQUERYATTRIBUTESFILE_TAG, name, |
michael@0 | 204 | attributes, file_info, &answer); |
michael@0 | 205 | |
michael@0 | 206 | operator delete(name, NT_ALLOC); |
michael@0 | 207 | |
michael@0 | 208 | if (SBOX_ALL_OK != code) |
michael@0 | 209 | break; |
michael@0 | 210 | |
michael@0 | 211 | return answer.nt_status; |
michael@0 | 212 | |
michael@0 | 213 | } while (false); |
michael@0 | 214 | |
michael@0 | 215 | return status; |
michael@0 | 216 | } |
michael@0 | 217 | |
michael@0 | 218 | NTSTATUS WINAPI TargetNtQueryFullAttributesFile( |
michael@0 | 219 | NtQueryFullAttributesFileFunction orig_QueryFullAttributes, |
michael@0 | 220 | POBJECT_ATTRIBUTES object_attributes, |
michael@0 | 221 | PFILE_NETWORK_OPEN_INFORMATION file_attributes) { |
michael@0 | 222 | // Check if the process can query it first. |
michael@0 | 223 | NTSTATUS status = orig_QueryFullAttributes(object_attributes, |
michael@0 | 224 | file_attributes); |
michael@0 | 225 | if (STATUS_ACCESS_DENIED != status) |
michael@0 | 226 | return status; |
michael@0 | 227 | |
michael@0 | 228 | // We don't trust that the IPC can work this early. |
michael@0 | 229 | if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) |
michael@0 | 230 | return status; |
michael@0 | 231 | |
michael@0 | 232 | do { |
michael@0 | 233 | if (!ValidParameter(file_attributes, sizeof(FILE_NETWORK_OPEN_INFORMATION), |
michael@0 | 234 | WRITE)) |
michael@0 | 235 | break; |
michael@0 | 236 | |
michael@0 | 237 | void* memory = GetGlobalIPCMemory(); |
michael@0 | 238 | if (NULL == memory) |
michael@0 | 239 | break; |
michael@0 | 240 | |
michael@0 | 241 | wchar_t* name = NULL; |
michael@0 | 242 | uint32 attributes = 0; |
michael@0 | 243 | NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes, |
michael@0 | 244 | NULL); |
michael@0 | 245 | if (!NT_SUCCESS(ret) || NULL == name) |
michael@0 | 246 | break; |
michael@0 | 247 | |
michael@0 | 248 | InOutCountedBuffer file_info(file_attributes, |
michael@0 | 249 | sizeof(FILE_NETWORK_OPEN_INFORMATION)); |
michael@0 | 250 | |
michael@0 | 251 | ULONG broker = FALSE; |
michael@0 | 252 | CountedParameterSet<FileName> params; |
michael@0 | 253 | params[FileName::NAME] = ParamPickerMake(name); |
michael@0 | 254 | params[FileName::BROKER] = ParamPickerMake(broker); |
michael@0 | 255 | |
michael@0 | 256 | if (!QueryBroker(IPC_NTQUERYFULLATTRIBUTESFILE_TAG, params.GetBase())) |
michael@0 | 257 | break; |
michael@0 | 258 | |
michael@0 | 259 | SharedMemIPCClient ipc(memory); |
michael@0 | 260 | CrossCallReturn answer = {0}; |
michael@0 | 261 | ResultCode code = CrossCall(ipc, IPC_NTQUERYFULLATTRIBUTESFILE_TAG, name, |
michael@0 | 262 | attributes, file_info, &answer); |
michael@0 | 263 | |
michael@0 | 264 | operator delete(name, NT_ALLOC); |
michael@0 | 265 | |
michael@0 | 266 | if (SBOX_ALL_OK != code) |
michael@0 | 267 | break; |
michael@0 | 268 | |
michael@0 | 269 | return answer.nt_status; |
michael@0 | 270 | } while (false); |
michael@0 | 271 | |
michael@0 | 272 | return status; |
michael@0 | 273 | } |
michael@0 | 274 | |
michael@0 | 275 | NTSTATUS WINAPI TargetNtSetInformationFile( |
michael@0 | 276 | NtSetInformationFileFunction orig_SetInformationFile, HANDLE file, |
michael@0 | 277 | PIO_STATUS_BLOCK io_status, PVOID file_info, ULONG length, |
michael@0 | 278 | FILE_INFORMATION_CLASS file_info_class) { |
michael@0 | 279 | // Check if the process can open it first. |
michael@0 | 280 | NTSTATUS status = orig_SetInformationFile(file, io_status, file_info, length, |
michael@0 | 281 | file_info_class); |
michael@0 | 282 | if (STATUS_ACCESS_DENIED != status) |
michael@0 | 283 | return status; |
michael@0 | 284 | |
michael@0 | 285 | // We don't trust that the IPC can work this early. |
michael@0 | 286 | if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) |
michael@0 | 287 | return status; |
michael@0 | 288 | |
michael@0 | 289 | do { |
michael@0 | 290 | void* memory = GetGlobalIPCMemory(); |
michael@0 | 291 | if (NULL == memory) |
michael@0 | 292 | break; |
michael@0 | 293 | |
michael@0 | 294 | if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE)) |
michael@0 | 295 | break; |
michael@0 | 296 | |
michael@0 | 297 | if (!ValidParameter(file_info, length, READ)) |
michael@0 | 298 | break; |
michael@0 | 299 | |
michael@0 | 300 | FILE_RENAME_INFORMATION* file_rename_info = |
michael@0 | 301 | reinterpret_cast<FILE_RENAME_INFORMATION*>(file_info); |
michael@0 | 302 | OBJECT_ATTRIBUTES object_attributes; |
michael@0 | 303 | UNICODE_STRING object_name; |
michael@0 | 304 | InitializeObjectAttributes(&object_attributes, &object_name, 0, NULL, NULL); |
michael@0 | 305 | |
michael@0 | 306 | __try { |
michael@0 | 307 | if (!IsSupportedRenameCall(file_rename_info, length, file_info_class)) |
michael@0 | 308 | break; |
michael@0 | 309 | |
michael@0 | 310 | object_attributes.RootDirectory = file_rename_info->RootDirectory; |
michael@0 | 311 | object_name.Buffer = file_rename_info->FileName; |
michael@0 | 312 | object_name.Length = object_name.MaximumLength = |
michael@0 | 313 | static_cast<USHORT>(file_rename_info->FileNameLength); |
michael@0 | 314 | } __except(EXCEPTION_EXECUTE_HANDLER) { |
michael@0 | 315 | break; |
michael@0 | 316 | } |
michael@0 | 317 | |
michael@0 | 318 | wchar_t* name; |
michael@0 | 319 | NTSTATUS ret = AllocAndCopyName(&object_attributes, &name, NULL, NULL); |
michael@0 | 320 | if (!NT_SUCCESS(ret) || !name) |
michael@0 | 321 | break; |
michael@0 | 322 | |
michael@0 | 323 | ULONG broker = FALSE; |
michael@0 | 324 | CountedParameterSet<FileName> params; |
michael@0 | 325 | params[FileName::NAME] = ParamPickerMake(name); |
michael@0 | 326 | params[FileName::BROKER] = ParamPickerMake(broker); |
michael@0 | 327 | |
michael@0 | 328 | if (!QueryBroker(IPC_NTSETINFO_RENAME_TAG, params.GetBase())) |
michael@0 | 329 | break; |
michael@0 | 330 | |
michael@0 | 331 | InOutCountedBuffer io_status_buffer(io_status, sizeof(IO_STATUS_BLOCK)); |
michael@0 | 332 | // This is actually not an InOut buffer, only In, but using InOut facility |
michael@0 | 333 | // really helps to simplify the code. |
michael@0 | 334 | InOutCountedBuffer file_info_buffer(file_info, length); |
michael@0 | 335 | |
michael@0 | 336 | SharedMemIPCClient ipc(memory); |
michael@0 | 337 | CrossCallReturn answer = {0}; |
michael@0 | 338 | ResultCode code = CrossCall(ipc, IPC_NTSETINFO_RENAME_TAG, file, |
michael@0 | 339 | io_status_buffer, file_info_buffer, length, |
michael@0 | 340 | file_info_class, &answer); |
michael@0 | 341 | |
michael@0 | 342 | if (SBOX_ALL_OK != code) |
michael@0 | 343 | break; |
michael@0 | 344 | |
michael@0 | 345 | status = answer.nt_status; |
michael@0 | 346 | } while (false); |
michael@0 | 347 | |
michael@0 | 348 | return status; |
michael@0 | 349 | } |
michael@0 | 350 | |
michael@0 | 351 | } // namespace sandbox |