| OLD | NEW |
| (Empty) |
| 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/src/filesystem_interception.h" | |
| 6 | |
| 7 #include "sandbox/src/crosscall_client.h" | |
| 8 #include "sandbox/src/ipc_tags.h" | |
| 9 #include "sandbox/src/policy_params.h" | |
| 10 #include "sandbox/src/policy_target.h" | |
| 11 #include "sandbox/src/sandbox_factory.h" | |
| 12 #include "sandbox/src/sandbox_nt_util.h" | |
| 13 #include "sandbox/src/sharedmem_ipc_client.h" | |
| 14 #include "sandbox/src/target_services.h" | |
| 15 | |
| 16 namespace sandbox { | |
| 17 | |
| 18 NTSTATUS 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 do { | |
| 39 if (!ValidParameter(file, sizeof(HANDLE), WRITE)) | |
| 40 break; | |
| 41 if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE)) | |
| 42 break; | |
| 43 | |
| 44 void* memory = GetGlobalIPCMemory(); | |
| 45 if (NULL == memory) | |
| 46 break; | |
| 47 | |
| 48 wchar_t* name; | |
| 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 | |
| 73 operator delete(name, NT_ALLOC); | |
| 74 | |
| 75 if (SBOX_ALL_OK != code) | |
| 76 break; | |
| 77 | |
| 78 if (!NT_SUCCESS(answer.nt_status)) | |
| 79 return answer.nt_status; | |
| 80 | |
| 81 __try { | |
| 82 *file = answer.handle; | |
| 83 io_status->Status = answer.nt_status; | |
| 84 io_status->Information = answer.extended[0].ulong_ptr; | |
| 85 status = io_status->Status; | |
| 86 } __except(EXCEPTION_EXECUTE_HANDLER) { | |
| 87 break; | |
| 88 } | |
| 89 } while (false); | |
| 90 | |
| 91 return status; | |
| 92 } | |
| 93 | |
| 94 NTSTATUS 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 do { | |
| 110 if (!ValidParameter(file, sizeof(HANDLE), WRITE)) | |
| 111 break; | |
| 112 if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE)) | |
| 113 break; | |
| 114 | |
| 115 void* memory = GetGlobalIPCMemory(); | |
| 116 if (NULL == memory) | |
| 117 break; | |
| 118 | |
| 119 wchar_t* name; | |
| 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 | |
| 141 operator delete(name, NT_ALLOC); | |
| 142 | |
| 143 if (SBOX_ALL_OK != code) | |
| 144 break; | |
| 145 | |
| 146 if (!NT_SUCCESS(answer.nt_status)) | |
| 147 return answer.nt_status; | |
| 148 | |
| 149 __try { | |
| 150 *file = answer.handle; | |
| 151 io_status->Status = answer.nt_status; | |
| 152 io_status->Information = answer.extended[0].ulong_ptr; | |
| 153 status = io_status->Status; | |
| 154 } __except(EXCEPTION_EXECUTE_HANDLER) { | |
| 155 break; | |
| 156 } | |
| 157 } while (false); | |
| 158 | |
| 159 return status; | |
| 160 } | |
| 161 | |
| 162 NTSTATUS 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 do { | |
| 176 if (!ValidParameter(file_attributes, sizeof(FILE_BASIC_INFORMATION), WRITE)) | |
| 177 break; | |
| 178 | |
| 179 void* memory = GetGlobalIPCMemory(); | |
| 180 if (NULL == memory) | |
| 181 break; | |
| 182 | |
| 183 wchar_t* name = NULL; | |
| 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 return status; | |
| 216 } | |
| 217 | |
| 218 NTSTATUS WINAPI TargetNtQueryFullAttributesFile( | |
| 219 NtQueryFullAttributesFileFunction orig_QueryFullAttributes, | |
| 220 POBJECT_ATTRIBUTES object_attributes, | |
| 221 PFILE_NETWORK_OPEN_INFORMATION file_attributes) { | |
| 222 // Check if the process can query it first. | |
| 223 NTSTATUS status = orig_QueryFullAttributes(object_attributes, | |
| 224 file_attributes); | |
| 225 if (STATUS_ACCESS_DENIED != status) | |
| 226 return status; | |
| 227 | |
| 228 // We don't trust that the IPC can work this early. | |
| 229 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) | |
| 230 return status; | |
| 231 | |
| 232 do { | |
| 233 if (!ValidParameter(file_attributes, sizeof(FILE_NETWORK_OPEN_INFORMATION), | |
| 234 WRITE)) | |
| 235 break; | |
| 236 | |
| 237 void* memory = GetGlobalIPCMemory(); | |
| 238 if (NULL == memory) | |
| 239 break; | |
| 240 | |
| 241 wchar_t* name = NULL; | |
| 242 uint32 attributes = 0; | |
| 243 NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes, | |
| 244 NULL); | |
| 245 if (!NT_SUCCESS(ret) || NULL == name) | |
| 246 break; | |
| 247 | |
| 248 InOutCountedBuffer file_info(file_attributes, | |
| 249 sizeof(FILE_NETWORK_OPEN_INFORMATION)); | |
| 250 | |
| 251 ULONG broker = FALSE; | |
| 252 CountedParameterSet<FileName> params; | |
| 253 params[FileName::NAME] = ParamPickerMake(name); | |
| 254 params[FileName::BROKER] = ParamPickerMake(broker); | |
| 255 | |
| 256 if (!QueryBroker(IPC_NTQUERYFULLATTRIBUTESFILE_TAG, params.GetBase())) | |
| 257 break; | |
| 258 | |
| 259 SharedMemIPCClient ipc(memory); | |
| 260 CrossCallReturn answer = {0}; | |
| 261 ResultCode code = CrossCall(ipc, IPC_NTQUERYFULLATTRIBUTESFILE_TAG, name, | |
| 262 attributes, file_info, &answer); | |
| 263 | |
| 264 operator delete(name, NT_ALLOC); | |
| 265 | |
| 266 if (SBOX_ALL_OK != code) | |
| 267 break; | |
| 268 | |
| 269 return answer.nt_status; | |
| 270 } while (false); | |
| 271 | |
| 272 return status; | |
| 273 } | |
| 274 | |
| 275 NTSTATUS WINAPI TargetNtSetInformationFile( | |
| 276 NtSetInformationFileFunction orig_SetInformationFile, HANDLE file, | |
| 277 PIO_STATUS_BLOCK io_status, PVOID file_info, ULONG length, | |
| 278 FILE_INFORMATION_CLASS file_info_class) { | |
| 279 // Check if the process can open it first. | |
| 280 NTSTATUS status = orig_SetInformationFile(file, io_status, file_info, length, | |
| 281 file_info_class); | |
| 282 if (STATUS_ACCESS_DENIED != status) | |
| 283 return status; | |
| 284 | |
| 285 // We don't trust that the IPC can work this early. | |
| 286 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) | |
| 287 return status; | |
| 288 | |
| 289 do { | |
| 290 void* memory = GetGlobalIPCMemory(); | |
| 291 if (NULL == memory) | |
| 292 break; | |
| 293 | |
| 294 if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE)) | |
| 295 break; | |
| 296 | |
| 297 if (!ValidParameter(file_info, length, READ)) | |
| 298 break; | |
| 299 | |
| 300 FILE_RENAME_INFORMATION* file_rename_info = | |
| 301 reinterpret_cast<FILE_RENAME_INFORMATION*>(file_info); | |
| 302 OBJECT_ATTRIBUTES object_attributes; | |
| 303 UNICODE_STRING object_name; | |
| 304 InitializeObjectAttributes(&object_attributes, &object_name, 0, NULL, NULL); | |
| 305 | |
| 306 __try { | |
| 307 if (!IsSupportedRenameCall(file_rename_info, length, file_info_class)) | |
| 308 break; | |
| 309 | |
| 310 object_attributes.RootDirectory = file_rename_info->RootDirectory; | |
| 311 object_name.Buffer = file_rename_info->FileName; | |
| 312 object_name.Length = object_name.MaximumLength = | |
| 313 static_cast<USHORT>(file_rename_info->FileNameLength); | |
| 314 } __except(EXCEPTION_EXECUTE_HANDLER) { | |
| 315 break; | |
| 316 } | |
| 317 | |
| 318 wchar_t* name; | |
| 319 NTSTATUS ret = AllocAndCopyName(&object_attributes, &name, NULL, NULL); | |
| 320 if (!NT_SUCCESS(ret) || !name) | |
| 321 break; | |
| 322 | |
| 323 ULONG broker = FALSE; | |
| 324 CountedParameterSet<FileName> params; | |
| 325 params[FileName::NAME] = ParamPickerMake(name); | |
| 326 params[FileName::BROKER] = ParamPickerMake(broker); | |
| 327 | |
| 328 if (!QueryBroker(IPC_NTSETINFO_RENAME_TAG, params.GetBase())) | |
| 329 break; | |
| 330 | |
| 331 InOutCountedBuffer io_status_buffer(io_status, sizeof(IO_STATUS_BLOCK)); | |
| 332 // This is actually not an InOut buffer, only In, but using InOut facility | |
| 333 // really helps to simplify the code. | |
| 334 InOutCountedBuffer file_info_buffer(file_info, length); | |
| 335 | |
| 336 SharedMemIPCClient ipc(memory); | |
| 337 CrossCallReturn answer = {0}; | |
| 338 ResultCode code = CrossCall(ipc, IPC_NTSETINFO_RENAME_TAG, file, | |
| 339 io_status_buffer, file_info_buffer, length, | |
| 340 file_info_class, &answer); | |
| 341 | |
| 342 if (SBOX_ALL_OK != code) | |
| 343 break; | |
| 344 | |
| 345 status = answer.nt_status; | |
| 346 } while (false); | |
| 347 | |
| 348 return status; | |
| 349 } | |
| 350 | |
| 351 } // namespace sandbox | |
| OLD | NEW |