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.
5 #include "sandbox/win/src/filesystem_interception.h"
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"
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)
34 // We don't trust that the IPC can work this early.
35 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
40 if (!ValidParameter(file, sizeof(HANDLE), WRITE))
42 if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE))
45 void* memory = GetGlobalIPCMemory();
49 uint32 attributes = 0;
50 NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes,
52 if (!NT_SUCCESS(ret) || NULL == name)
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);
62 if (!QueryBroker(IPC_NTCREATEFILE_TAG, params.GetBase()))
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)
75 if (!NT_SUCCESS(answer.nt_status))
76 return answer.nt_status;
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) {
89 operator delete(name, NT_ALLOC);
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,
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)
105 // We don't trust that the IPC can work this early.
106 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
109 wchar_t* name = NULL;
111 if (!ValidParameter(file, sizeof(HANDLE), WRITE))
113 if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE))
116 void* memory = GetGlobalIPCMemory();
121 NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes,
123 if (!NT_SUCCESS(ret) || NULL == name)
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);
133 if (!QueryBroker(IPC_NTOPENFILE_TAG, params.GetBase()))
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)
143 if (!NT_SUCCESS(answer.nt_status))
144 return answer.nt_status;
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) {
157 operator delete(name, NT_ALLOC);
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)
171 // We don't trust that the IPC can work this early.
172 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
175 wchar_t* name = NULL;
177 if (!ValidParameter(file_attributes, sizeof(FILE_BASIC_INFORMATION), WRITE))
180 void* memory = GetGlobalIPCMemory();
184 uint32 attributes = 0;
185 NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes,
187 if (!NT_SUCCESS(ret) || NULL == name)
190 InOutCountedBuffer file_info(file_attributes,
191 sizeof(FILE_BASIC_INFORMATION));
193 ULONG broker = FALSE;
194 CountedParameterSet<FileName> params;
195 params[FileName::NAME] = ParamPickerMake(name);
196 params[FileName::BROKER] = ParamPickerMake(broker);
198 if (!QueryBroker(IPC_NTQUERYATTRIBUTESFILE_TAG, params.GetBase()))
201 SharedMemIPCClient ipc(memory);
202 CrossCallReturn answer = {0};
203 ResultCode code = CrossCall(ipc, IPC_NTQUERYATTRIBUTESFILE_TAG, name,
204 attributes, file_info, &answer);
206 operator delete(name, NT_ALLOC);
208 if (SBOX_ALL_OK != code)
211 return answer.nt_status;
216 operator delete(name, NT_ALLOC);
221 NTSTATUS 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,
228 if (STATUS_ACCESS_DENIED != status)
231 // We don't trust that the IPC can work this early.
232 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
235 wchar_t* name = NULL;
237 if (!ValidParameter(file_attributes, sizeof(FILE_NETWORK_OPEN_INFORMATION),
241 void* memory = GetGlobalIPCMemory();
245 uint32 attributes = 0;
246 NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes,
248 if (!NT_SUCCESS(ret) || NULL == name)
251 InOutCountedBuffer file_info(file_attributes,
252 sizeof(FILE_NETWORK_OPEN_INFORMATION));
254 ULONG broker = FALSE;
255 CountedParameterSet<FileName> params;
256 params[FileName::NAME] = ParamPickerMake(name);
257 params[FileName::BROKER] = ParamPickerMake(broker);
259 if (!QueryBroker(IPC_NTQUERYFULLATTRIBUTESFILE_TAG, params.GetBase()))
262 SharedMemIPCClient ipc(memory);
263 CrossCallReturn answer = {0};
264 ResultCode code = CrossCall(ipc, IPC_NTQUERYFULLATTRIBUTESFILE_TAG, name,
265 attributes, file_info, &answer);
267 operator delete(name, NT_ALLOC);
269 if (SBOX_ALL_OK != code)
272 return answer.nt_status;
276 operator delete(name, NT_ALLOC);
281 NTSTATUS 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,
288 if (STATUS_ACCESS_DENIED != status)
291 // We don't trust that the IPC can work this early.
292 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
295 wchar_t* name = NULL;
297 void* memory = GetGlobalIPCMemory();
301 if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE))
304 if (!ValidParameter(file_info, length, READ))
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);
314 if (!IsSupportedRenameCall(file_rename_info, length, file_info_class))
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) {
325 NTSTATUS ret = AllocAndCopyName(&object_attributes, &name, NULL, NULL);
326 if (!NT_SUCCESS(ret) || !name)
329 ULONG broker = FALSE;
330 CountedParameterSet<FileName> params;
331 params[FileName::NAME] = ParamPickerMake(name);
332 params[FileName::BROKER] = ParamPickerMake(broker);
334 if (!QueryBroker(IPC_NTSETINFO_RENAME_TAG, params.GetBase()))
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);
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);
348 if (SBOX_ALL_OK != code)
351 status = answer.nt_status;
355 operator delete(name, NT_ALLOC);
360 } // namespace sandbox