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
)
55 uint32 desired_access_uint32
= desired_access
;
56 uint32 options_uint32
= options
;
57 uint32 disposition_uint32
= disposition
;
58 uint32 broker
= FALSE
;
59 CountedParameterSet
<OpenFile
> params
;
60 params
[OpenFile::NAME
] = ParamPickerMake(name
);
61 params
[OpenFile::ACCESS
] = ParamPickerMake(desired_access_uint32
);
62 params
[OpenFile::DISPOSITION
] = ParamPickerMake(disposition_uint32
);
63 params
[OpenFile::OPTIONS
] = ParamPickerMake(options_uint32
);
64 params
[OpenFile::BROKER
] = ParamPickerMake(broker
);
66 if (!QueryBroker(IPC_NTCREATEFILE_TAG
, params
.GetBase()))
69 SharedMemIPCClient
ipc(memory
);
70 CrossCallReturn answer
= {0};
71 // The following call must match in the parameters with
72 // FilesystemDispatcher::ProcessNtCreateFile.
73 ResultCode code
= CrossCall(ipc
, IPC_NTCREATEFILE_TAG
, name
, attributes
,
74 desired_access_uint32
, file_attributes
, sharing
,
75 disposition
, options_uint32
, &answer
);
76 if (SBOX_ALL_OK
!= code
)
79 status
= answer
.nt_status
;
81 if (!NT_SUCCESS(answer
.nt_status
))
85 *file
= answer
.handle
;
86 io_status
->Status
= answer
.nt_status
;
87 io_status
->Information
= answer
.extended
[0].ulong_ptr
;
88 } __except(EXCEPTION_EXECUTE_HANDLER
) {
94 operator delete(name
, NT_ALLOC
);
99 NTSTATUS WINAPI
TargetNtOpenFile(NtOpenFileFunction orig_OpenFile
, PHANDLE file
,
100 ACCESS_MASK desired_access
,
101 POBJECT_ATTRIBUTES object_attributes
,
102 PIO_STATUS_BLOCK io_status
, ULONG sharing
,
104 // Check if the process can open it first.
105 NTSTATUS status
= orig_OpenFile(file
, desired_access
, object_attributes
,
106 io_status
, sharing
, options
);
107 if (STATUS_ACCESS_DENIED
!= status
)
110 // We don't trust that the IPC can work this early.
111 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
114 wchar_t* name
= NULL
;
116 if (!ValidParameter(file
, sizeof(HANDLE
), WRITE
))
118 if (!ValidParameter(io_status
, sizeof(IO_STATUS_BLOCK
), WRITE
))
121 void* memory
= GetGlobalIPCMemory();
126 NTSTATUS ret
= AllocAndCopyName(object_attributes
, &name
, &attributes
,
128 if (!NT_SUCCESS(ret
) || NULL
== name
)
131 uint32 desired_access_uint32
= desired_access
;
132 uint32 options_uint32
= options
;
133 uint32 disposition_uint32
= FILE_OPEN
;
134 uint32 broker
= FALSE
;
135 CountedParameterSet
<OpenFile
> params
;
136 params
[OpenFile::NAME
] = ParamPickerMake(name
);
137 params
[OpenFile::ACCESS
] = ParamPickerMake(desired_access_uint32
);
138 params
[OpenFile::DISPOSITION
] = ParamPickerMake(disposition_uint32
);
139 params
[OpenFile::OPTIONS
] = ParamPickerMake(options_uint32
);
140 params
[OpenFile::BROKER
] = ParamPickerMake(broker
);
142 if (!QueryBroker(IPC_NTOPENFILE_TAG
, params
.GetBase()))
145 SharedMemIPCClient
ipc(memory
);
146 CrossCallReturn answer
= {0};
147 ResultCode code
= CrossCall(ipc
, IPC_NTOPENFILE_TAG
, name
, attributes
,
148 desired_access_uint32
, sharing
, options_uint32
,
150 if (SBOX_ALL_OK
!= code
)
153 status
= answer
.nt_status
;
155 if (!NT_SUCCESS(answer
.nt_status
))
159 *file
= answer
.handle
;
160 io_status
->Status
= answer
.nt_status
;
161 io_status
->Information
= answer
.extended
[0].ulong_ptr
;
162 } __except(EXCEPTION_EXECUTE_HANDLER
) {
168 operator delete(name
, NT_ALLOC
);
173 NTSTATUS WINAPI
TargetNtQueryAttributesFile(
174 NtQueryAttributesFileFunction orig_QueryAttributes
,
175 POBJECT_ATTRIBUTES object_attributes
,
176 PFILE_BASIC_INFORMATION file_attributes
) {
177 // Check if the process can query it first.
178 NTSTATUS status
= orig_QueryAttributes(object_attributes
, file_attributes
);
179 if (STATUS_ACCESS_DENIED
!= status
)
182 // We don't trust that the IPC can work this early.
183 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
186 wchar_t* name
= NULL
;
188 if (!ValidParameter(file_attributes
, sizeof(FILE_BASIC_INFORMATION
), WRITE
))
191 void* memory
= GetGlobalIPCMemory();
195 uint32 attributes
= 0;
196 NTSTATUS ret
= AllocAndCopyName(object_attributes
, &name
, &attributes
,
198 if (!NT_SUCCESS(ret
) || NULL
== name
)
201 InOutCountedBuffer
file_info(file_attributes
,
202 sizeof(FILE_BASIC_INFORMATION
));
204 uint32 broker
= FALSE
;
205 CountedParameterSet
<FileName
> params
;
206 params
[FileName::NAME
] = ParamPickerMake(name
);
207 params
[FileName::BROKER
] = ParamPickerMake(broker
);
209 if (!QueryBroker(IPC_NTQUERYATTRIBUTESFILE_TAG
, params
.GetBase()))
212 SharedMemIPCClient
ipc(memory
);
213 CrossCallReturn answer
= {0};
214 ResultCode code
= CrossCall(ipc
, IPC_NTQUERYATTRIBUTESFILE_TAG
, name
,
215 attributes
, file_info
, &answer
);
217 if (SBOX_ALL_OK
!= code
)
220 status
= answer
.nt_status
;
225 operator delete(name
, NT_ALLOC
);
230 NTSTATUS WINAPI
TargetNtQueryFullAttributesFile(
231 NtQueryFullAttributesFileFunction orig_QueryFullAttributes
,
232 POBJECT_ATTRIBUTES object_attributes
,
233 PFILE_NETWORK_OPEN_INFORMATION file_attributes
) {
234 // Check if the process can query it first.
235 NTSTATUS status
= orig_QueryFullAttributes(object_attributes
,
237 if (STATUS_ACCESS_DENIED
!= status
)
240 // We don't trust that the IPC can work this early.
241 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
244 wchar_t* name
= NULL
;
246 if (!ValidParameter(file_attributes
, sizeof(FILE_NETWORK_OPEN_INFORMATION
),
250 void* memory
= GetGlobalIPCMemory();
254 uint32 attributes
= 0;
255 NTSTATUS ret
= AllocAndCopyName(object_attributes
, &name
, &attributes
,
257 if (!NT_SUCCESS(ret
) || NULL
== name
)
260 InOutCountedBuffer
file_info(file_attributes
,
261 sizeof(FILE_NETWORK_OPEN_INFORMATION
));
263 uint32 broker
= FALSE
;
264 CountedParameterSet
<FileName
> params
;
265 params
[FileName::NAME
] = ParamPickerMake(name
);
266 params
[FileName::BROKER
] = ParamPickerMake(broker
);
268 if (!QueryBroker(IPC_NTQUERYFULLATTRIBUTESFILE_TAG
, params
.GetBase()))
271 SharedMemIPCClient
ipc(memory
);
272 CrossCallReturn answer
= {0};
273 ResultCode code
= CrossCall(ipc
, IPC_NTQUERYFULLATTRIBUTESFILE_TAG
, name
,
274 attributes
, file_info
, &answer
);
276 if (SBOX_ALL_OK
!= code
)
279 status
= answer
.nt_status
;
283 operator delete(name
, NT_ALLOC
);
288 NTSTATUS WINAPI
TargetNtSetInformationFile(
289 NtSetInformationFileFunction orig_SetInformationFile
, HANDLE file
,
290 PIO_STATUS_BLOCK io_status
, PVOID file_info
, ULONG length
,
291 FILE_INFORMATION_CLASS file_info_class
) {
292 // Check if the process can open it first.
293 NTSTATUS status
= orig_SetInformationFile(file
, io_status
, file_info
, length
,
295 if (STATUS_ACCESS_DENIED
!= status
)
298 // We don't trust that the IPC can work this early.
299 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
302 wchar_t* name
= NULL
;
304 void* memory
= GetGlobalIPCMemory();
308 if (!ValidParameter(io_status
, sizeof(IO_STATUS_BLOCK
), WRITE
))
311 if (!ValidParameter(file_info
, length
, READ
))
314 FILE_RENAME_INFORMATION
* file_rename_info
=
315 reinterpret_cast<FILE_RENAME_INFORMATION
*>(file_info
);
316 OBJECT_ATTRIBUTES object_attributes
;
317 UNICODE_STRING object_name
;
318 InitializeObjectAttributes(&object_attributes
, &object_name
, 0, NULL
, NULL
);
321 if (!IsSupportedRenameCall(file_rename_info
, length
, file_info_class
))
324 object_attributes
.RootDirectory
= file_rename_info
->RootDirectory
;
325 object_name
.Buffer
= file_rename_info
->FileName
;
326 object_name
.Length
= object_name
.MaximumLength
=
327 static_cast<USHORT
>(file_rename_info
->FileNameLength
);
328 } __except(EXCEPTION_EXECUTE_HANDLER
) {
332 NTSTATUS ret
= AllocAndCopyName(&object_attributes
, &name
, NULL
, NULL
);
333 if (!NT_SUCCESS(ret
) || !name
)
336 uint32 broker
= FALSE
;
337 CountedParameterSet
<FileName
> params
;
338 params
[FileName::NAME
] = ParamPickerMake(name
);
339 params
[FileName::BROKER
] = ParamPickerMake(broker
);
341 if (!QueryBroker(IPC_NTSETINFO_RENAME_TAG
, params
.GetBase()))
344 InOutCountedBuffer
io_status_buffer(io_status
, sizeof(IO_STATUS_BLOCK
));
345 // This is actually not an InOut buffer, only In, but using InOut facility
346 // really helps to simplify the code.
347 InOutCountedBuffer
file_info_buffer(file_info
, length
);
349 SharedMemIPCClient
ipc(memory
);
350 CrossCallReturn answer
= {0};
351 ResultCode code
= CrossCall(ipc
, IPC_NTSETINFO_RENAME_TAG
, file
,
352 io_status_buffer
, file_info_buffer
, length
,
353 file_info_class
, &answer
);
355 if (SBOX_ALL_OK
!= code
)
358 status
= answer
.nt_status
;
362 operator delete(name
, NT_ALLOC
);
367 } // namespace sandbox