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())
39 if (!ValidParameter(file
, sizeof(HANDLE
), WRITE
))
41 if (!ValidParameter(io_status
, sizeof(IO_STATUS_BLOCK
), WRITE
))
44 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
);
73 operator delete(name
, NT_ALLOC
);
75 if (SBOX_ALL_OK
!= code
)
78 if (!NT_SUCCESS(answer
.nt_status
))
79 return answer
.nt_status
;
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
) {
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())
110 if (!ValidParameter(file
, sizeof(HANDLE
), WRITE
))
112 if (!ValidParameter(io_status
, sizeof(IO_STATUS_BLOCK
), WRITE
))
115 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
);
141 operator delete(name
, NT_ALLOC
);
143 if (SBOX_ALL_OK
!= code
)
146 if (!NT_SUCCESS(answer
.nt_status
))
147 return answer
.nt_status
;
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
) {
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())
176 if (!ValidParameter(file_attributes
, sizeof(FILE_BASIC_INFORMATION
), WRITE
))
179 void* memory
= GetGlobalIPCMemory();
183 wchar_t* name
= NULL
;
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
;
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
,
225 if (STATUS_ACCESS_DENIED
!= status
)
228 // We don't trust that the IPC can work this early.
229 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
233 if (!ValidParameter(file_attributes
, sizeof(FILE_NETWORK_OPEN_INFORMATION
),
237 void* memory
= GetGlobalIPCMemory();
241 wchar_t* name
= NULL
;
242 uint32 attributes
= 0;
243 NTSTATUS ret
= AllocAndCopyName(object_attributes
, &name
, &attributes
,
245 if (!NT_SUCCESS(ret
) || NULL
== name
)
248 InOutCountedBuffer
file_info(file_attributes
,
249 sizeof(FILE_NETWORK_OPEN_INFORMATION
));
251 ULONG broker
= FALSE
;
252 CountedParameterSet
<FileName
> params
;
253 params
[FileName::NAME
] = ParamPickerMake(name
);
254 params
[FileName::BROKER
] = ParamPickerMake(broker
);
256 if (!QueryBroker(IPC_NTQUERYFULLATTRIBUTESFILE_TAG
, params
.GetBase()))
259 SharedMemIPCClient
ipc(memory
);
260 CrossCallReturn answer
= {0};
261 ResultCode code
= CrossCall(ipc
, IPC_NTQUERYFULLATTRIBUTESFILE_TAG
, name
,
262 attributes
, file_info
, &answer
);
264 operator delete(name
, NT_ALLOC
);
266 if (SBOX_ALL_OK
!= code
)
269 return answer
.nt_status
;
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
,
282 if (STATUS_ACCESS_DENIED
!= status
)
285 // We don't trust that the IPC can work this early.
286 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
290 void* memory
= GetGlobalIPCMemory();
294 if (!ValidParameter(io_status
, sizeof(IO_STATUS_BLOCK
), WRITE
))
297 if (!ValidParameter(file_info
, length
, READ
))
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
);
307 if (!IsSupportedRenameCall(file_rename_info
, length
, file_info_class
))
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
) {
319 NTSTATUS ret
= AllocAndCopyName(&object_attributes
, &name
, NULL
, NULL
);
320 if (!NT_SUCCESS(ret
) || !name
)
323 ULONG broker
= FALSE
;
324 CountedParameterSet
<FileName
> params
;
325 params
[FileName::NAME
] = ParamPickerMake(name
);
326 params
[FileName::BROKER
] = ParamPickerMake(broker
);
328 if (!QueryBroker(IPC_NTSETINFO_RENAME_TAG
, params
.GetBase()))
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
);
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
);
342 if (SBOX_ALL_OK
!= code
)
345 status
= answer
.nt_status
;
351 } // namespace sandbox