1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/sandbox/win/src/filesystem_interception.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,351 @@ 1.4 +// Copyright (c) 2006-2008 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/filesystem_interception.h" 1.9 + 1.10 +#include "sandbox/win/src/crosscall_client.h" 1.11 +#include "sandbox/win/src/ipc_tags.h" 1.12 +#include "sandbox/win/src/policy_params.h" 1.13 +#include "sandbox/win/src/policy_target.h" 1.14 +#include "sandbox/win/src/sandbox_factory.h" 1.15 +#include "sandbox/win/src/sandbox_nt_util.h" 1.16 +#include "sandbox/win/src/sharedmem_ipc_client.h" 1.17 +#include "sandbox/win/src/target_services.h" 1.18 + 1.19 +namespace sandbox { 1.20 + 1.21 +NTSTATUS WINAPI TargetNtCreateFile(NtCreateFileFunction orig_CreateFile, 1.22 + PHANDLE file, ACCESS_MASK desired_access, 1.23 + POBJECT_ATTRIBUTES object_attributes, 1.24 + PIO_STATUS_BLOCK io_status, 1.25 + PLARGE_INTEGER allocation_size, 1.26 + ULONG file_attributes, ULONG sharing, 1.27 + ULONG disposition, ULONG options, 1.28 + PVOID ea_buffer, ULONG ea_length) { 1.29 + // Check if the process can open it first. 1.30 + NTSTATUS status = orig_CreateFile(file, desired_access, object_attributes, 1.31 + io_status, allocation_size, 1.32 + file_attributes, sharing, disposition, 1.33 + options, ea_buffer, ea_length); 1.34 + if (STATUS_ACCESS_DENIED != status) 1.35 + return status; 1.36 + 1.37 + // We don't trust that the IPC can work this early. 1.38 + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) 1.39 + return status; 1.40 + 1.41 + do { 1.42 + if (!ValidParameter(file, sizeof(HANDLE), WRITE)) 1.43 + break; 1.44 + if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE)) 1.45 + break; 1.46 + 1.47 + void* memory = GetGlobalIPCMemory(); 1.48 + if (NULL == memory) 1.49 + break; 1.50 + 1.51 + wchar_t* name; 1.52 + uint32 attributes = 0; 1.53 + NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes, 1.54 + NULL); 1.55 + if (!NT_SUCCESS(ret) || NULL == name) 1.56 + break; 1.57 + 1.58 + ULONG broker = FALSE; 1.59 + CountedParameterSet<OpenFile> params; 1.60 + params[OpenFile::NAME] = ParamPickerMake(name); 1.61 + params[OpenFile::ACCESS] = ParamPickerMake(desired_access); 1.62 + params[OpenFile::OPTIONS] = ParamPickerMake(options); 1.63 + params[OpenFile::BROKER] = ParamPickerMake(broker); 1.64 + 1.65 + if (!QueryBroker(IPC_NTCREATEFILE_TAG, params.GetBase())) 1.66 + break; 1.67 + 1.68 + SharedMemIPCClient ipc(memory); 1.69 + CrossCallReturn answer = {0}; 1.70 + // The following call must match in the parameters with 1.71 + // FilesystemDispatcher::ProcessNtCreateFile. 1.72 + ResultCode code = CrossCall(ipc, IPC_NTCREATEFILE_TAG, name, attributes, 1.73 + desired_access, file_attributes, sharing, 1.74 + disposition, options, &answer); 1.75 + 1.76 + operator delete(name, NT_ALLOC); 1.77 + 1.78 + if (SBOX_ALL_OK != code) 1.79 + break; 1.80 + 1.81 + if (!NT_SUCCESS(answer.nt_status)) 1.82 + return answer.nt_status; 1.83 + 1.84 + __try { 1.85 + *file = answer.handle; 1.86 + io_status->Status = answer.nt_status; 1.87 + io_status->Information = answer.extended[0].ulong_ptr; 1.88 + status = io_status->Status; 1.89 + } __except(EXCEPTION_EXECUTE_HANDLER) { 1.90 + break; 1.91 + } 1.92 + } while (false); 1.93 + 1.94 + return status; 1.95 +} 1.96 + 1.97 +NTSTATUS WINAPI TargetNtOpenFile(NtOpenFileFunction orig_OpenFile, PHANDLE file, 1.98 + ACCESS_MASK desired_access, 1.99 + POBJECT_ATTRIBUTES object_attributes, 1.100 + PIO_STATUS_BLOCK io_status, ULONG sharing, 1.101 + ULONG options) { 1.102 + // Check if the process can open it first. 1.103 + NTSTATUS status = orig_OpenFile(file, desired_access, object_attributes, 1.104 + io_status, sharing, options); 1.105 + if (STATUS_ACCESS_DENIED != status) 1.106 + return status; 1.107 + 1.108 + // We don't trust that the IPC can work this early. 1.109 + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) 1.110 + return status; 1.111 + 1.112 + do { 1.113 + if (!ValidParameter(file, sizeof(HANDLE), WRITE)) 1.114 + break; 1.115 + if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE)) 1.116 + break; 1.117 + 1.118 + void* memory = GetGlobalIPCMemory(); 1.119 + if (NULL == memory) 1.120 + break; 1.121 + 1.122 + wchar_t* name; 1.123 + uint32 attributes; 1.124 + NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes, 1.125 + NULL); 1.126 + if (!NT_SUCCESS(ret) || NULL == name) 1.127 + break; 1.128 + 1.129 + ULONG broker = FALSE; 1.130 + CountedParameterSet<OpenFile> params; 1.131 + params[OpenFile::NAME] = ParamPickerMake(name); 1.132 + params[OpenFile::ACCESS] = ParamPickerMake(desired_access); 1.133 + params[OpenFile::OPTIONS] = ParamPickerMake(options); 1.134 + params[OpenFile::BROKER] = ParamPickerMake(broker); 1.135 + 1.136 + if (!QueryBroker(IPC_NTOPENFILE_TAG, params.GetBase())) 1.137 + break; 1.138 + 1.139 + SharedMemIPCClient ipc(memory); 1.140 + CrossCallReturn answer = {0}; 1.141 + ResultCode code = CrossCall(ipc, IPC_NTOPENFILE_TAG, name, attributes, 1.142 + desired_access, sharing, options, &answer); 1.143 + 1.144 + operator delete(name, NT_ALLOC); 1.145 + 1.146 + if (SBOX_ALL_OK != code) 1.147 + break; 1.148 + 1.149 + if (!NT_SUCCESS(answer.nt_status)) 1.150 + return answer.nt_status; 1.151 + 1.152 + __try { 1.153 + *file = answer.handle; 1.154 + io_status->Status = answer.nt_status; 1.155 + io_status->Information = answer.extended[0].ulong_ptr; 1.156 + status = io_status->Status; 1.157 + } __except(EXCEPTION_EXECUTE_HANDLER) { 1.158 + break; 1.159 + } 1.160 + } while (false); 1.161 + 1.162 + return status; 1.163 +} 1.164 + 1.165 +NTSTATUS WINAPI TargetNtQueryAttributesFile( 1.166 + NtQueryAttributesFileFunction orig_QueryAttributes, 1.167 + POBJECT_ATTRIBUTES object_attributes, 1.168 + PFILE_BASIC_INFORMATION file_attributes) { 1.169 + // Check if the process can query it first. 1.170 + NTSTATUS status = orig_QueryAttributes(object_attributes, file_attributes); 1.171 + if (STATUS_ACCESS_DENIED != status) 1.172 + return status; 1.173 + 1.174 + // We don't trust that the IPC can work this early. 1.175 + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) 1.176 + return status; 1.177 + 1.178 + do { 1.179 + if (!ValidParameter(file_attributes, sizeof(FILE_BASIC_INFORMATION), WRITE)) 1.180 + break; 1.181 + 1.182 + void* memory = GetGlobalIPCMemory(); 1.183 + if (NULL == memory) 1.184 + break; 1.185 + 1.186 + wchar_t* name = NULL; 1.187 + uint32 attributes = 0; 1.188 + NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes, 1.189 + NULL); 1.190 + if (!NT_SUCCESS(ret) || NULL == name) 1.191 + break; 1.192 + 1.193 + InOutCountedBuffer file_info(file_attributes, 1.194 + sizeof(FILE_BASIC_INFORMATION)); 1.195 + 1.196 + ULONG broker = FALSE; 1.197 + CountedParameterSet<FileName> params; 1.198 + params[FileName::NAME] = ParamPickerMake(name); 1.199 + params[FileName::BROKER] = ParamPickerMake(broker); 1.200 + 1.201 + if (!QueryBroker(IPC_NTQUERYATTRIBUTESFILE_TAG, params.GetBase())) 1.202 + break; 1.203 + 1.204 + SharedMemIPCClient ipc(memory); 1.205 + CrossCallReturn answer = {0}; 1.206 + ResultCode code = CrossCall(ipc, IPC_NTQUERYATTRIBUTESFILE_TAG, name, 1.207 + attributes, file_info, &answer); 1.208 + 1.209 + operator delete(name, NT_ALLOC); 1.210 + 1.211 + if (SBOX_ALL_OK != code) 1.212 + break; 1.213 + 1.214 + return answer.nt_status; 1.215 + 1.216 + } while (false); 1.217 + 1.218 + return status; 1.219 +} 1.220 + 1.221 +NTSTATUS WINAPI TargetNtQueryFullAttributesFile( 1.222 + NtQueryFullAttributesFileFunction orig_QueryFullAttributes, 1.223 + POBJECT_ATTRIBUTES object_attributes, 1.224 + PFILE_NETWORK_OPEN_INFORMATION file_attributes) { 1.225 + // Check if the process can query it first. 1.226 + NTSTATUS status = orig_QueryFullAttributes(object_attributes, 1.227 + file_attributes); 1.228 + if (STATUS_ACCESS_DENIED != status) 1.229 + return status; 1.230 + 1.231 + // We don't trust that the IPC can work this early. 1.232 + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) 1.233 + return status; 1.234 + 1.235 + do { 1.236 + if (!ValidParameter(file_attributes, sizeof(FILE_NETWORK_OPEN_INFORMATION), 1.237 + WRITE)) 1.238 + break; 1.239 + 1.240 + void* memory = GetGlobalIPCMemory(); 1.241 + if (NULL == memory) 1.242 + break; 1.243 + 1.244 + wchar_t* name = NULL; 1.245 + uint32 attributes = 0; 1.246 + NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes, 1.247 + NULL); 1.248 + if (!NT_SUCCESS(ret) || NULL == name) 1.249 + break; 1.250 + 1.251 + InOutCountedBuffer file_info(file_attributes, 1.252 + sizeof(FILE_NETWORK_OPEN_INFORMATION)); 1.253 + 1.254 + ULONG broker = FALSE; 1.255 + CountedParameterSet<FileName> params; 1.256 + params[FileName::NAME] = ParamPickerMake(name); 1.257 + params[FileName::BROKER] = ParamPickerMake(broker); 1.258 + 1.259 + if (!QueryBroker(IPC_NTQUERYFULLATTRIBUTESFILE_TAG, params.GetBase())) 1.260 + break; 1.261 + 1.262 + SharedMemIPCClient ipc(memory); 1.263 + CrossCallReturn answer = {0}; 1.264 + ResultCode code = CrossCall(ipc, IPC_NTQUERYFULLATTRIBUTESFILE_TAG, name, 1.265 + attributes, file_info, &answer); 1.266 + 1.267 + operator delete(name, NT_ALLOC); 1.268 + 1.269 + if (SBOX_ALL_OK != code) 1.270 + break; 1.271 + 1.272 + return answer.nt_status; 1.273 + } while (false); 1.274 + 1.275 + return status; 1.276 +} 1.277 + 1.278 +NTSTATUS WINAPI TargetNtSetInformationFile( 1.279 + NtSetInformationFileFunction orig_SetInformationFile, HANDLE file, 1.280 + PIO_STATUS_BLOCK io_status, PVOID file_info, ULONG length, 1.281 + FILE_INFORMATION_CLASS file_info_class) { 1.282 + // Check if the process can open it first. 1.283 + NTSTATUS status = orig_SetInformationFile(file, io_status, file_info, length, 1.284 + file_info_class); 1.285 + if (STATUS_ACCESS_DENIED != status) 1.286 + return status; 1.287 + 1.288 + // We don't trust that the IPC can work this early. 1.289 + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) 1.290 + return status; 1.291 + 1.292 + do { 1.293 + void* memory = GetGlobalIPCMemory(); 1.294 + if (NULL == memory) 1.295 + break; 1.296 + 1.297 + if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE)) 1.298 + break; 1.299 + 1.300 + if (!ValidParameter(file_info, length, READ)) 1.301 + break; 1.302 + 1.303 + FILE_RENAME_INFORMATION* file_rename_info = 1.304 + reinterpret_cast<FILE_RENAME_INFORMATION*>(file_info); 1.305 + OBJECT_ATTRIBUTES object_attributes; 1.306 + UNICODE_STRING object_name; 1.307 + InitializeObjectAttributes(&object_attributes, &object_name, 0, NULL, NULL); 1.308 + 1.309 + __try { 1.310 + if (!IsSupportedRenameCall(file_rename_info, length, file_info_class)) 1.311 + break; 1.312 + 1.313 + object_attributes.RootDirectory = file_rename_info->RootDirectory; 1.314 + object_name.Buffer = file_rename_info->FileName; 1.315 + object_name.Length = object_name.MaximumLength = 1.316 + static_cast<USHORT>(file_rename_info->FileNameLength); 1.317 + } __except(EXCEPTION_EXECUTE_HANDLER) { 1.318 + break; 1.319 + } 1.320 + 1.321 + wchar_t* name; 1.322 + NTSTATUS ret = AllocAndCopyName(&object_attributes, &name, NULL, NULL); 1.323 + if (!NT_SUCCESS(ret) || !name) 1.324 + break; 1.325 + 1.326 + ULONG broker = FALSE; 1.327 + CountedParameterSet<FileName> params; 1.328 + params[FileName::NAME] = ParamPickerMake(name); 1.329 + params[FileName::BROKER] = ParamPickerMake(broker); 1.330 + 1.331 + if (!QueryBroker(IPC_NTSETINFO_RENAME_TAG, params.GetBase())) 1.332 + break; 1.333 + 1.334 + InOutCountedBuffer io_status_buffer(io_status, sizeof(IO_STATUS_BLOCK)); 1.335 + // This is actually not an InOut buffer, only In, but using InOut facility 1.336 + // really helps to simplify the code. 1.337 + InOutCountedBuffer file_info_buffer(file_info, length); 1.338 + 1.339 + SharedMemIPCClient ipc(memory); 1.340 + CrossCallReturn answer = {0}; 1.341 + ResultCode code = CrossCall(ipc, IPC_NTSETINFO_RENAME_TAG, file, 1.342 + io_status_buffer, file_info_buffer, length, 1.343 + file_info_class, &answer); 1.344 + 1.345 + if (SBOX_ALL_OK != code) 1.346 + break; 1.347 + 1.348 + status = answer.nt_status; 1.349 + } while (false); 1.350 + 1.351 + return status; 1.352 +} 1.353 + 1.354 +} // namespace sandbox