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