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 broker
= FALSE
;
58 CountedParameterSet
<OpenFile
> params
;
59 params
[OpenFile::NAME
] = ParamPickerMake(name
);
60 params
[OpenFile::ACCESS
] = ParamPickerMake(desired_access_uint32
);
61 params
[OpenFile::OPTIONS
] = ParamPickerMake(options_uint32
);
62 params
[OpenFile::BROKER
] = ParamPickerMake(broker
);
64 if (!QueryBroker(IPC_NTCREATEFILE_TAG
, params
.GetBase()))
67 SharedMemIPCClient
ipc(memory
);
68 CrossCallReturn answer
= {0};
69 // The following call must match in the parameters with
70 // FilesystemDispatcher::ProcessNtCreateFile.
71 ResultCode code
= CrossCall(ipc
, IPC_NTCREATEFILE_TAG
, name
, attributes
,
72 desired_access_uint32
, file_attributes
, sharing
,
73 disposition
, options_uint32
, &answer
);
74 if (SBOX_ALL_OK
!= code
)
77 if (!NT_SUCCESS(answer
.nt_status
))
78 return answer
.nt_status
;
81 *file
= answer
.handle
;
82 io_status
->Status
= answer
.nt_status
;
83 io_status
->Information
= answer
.extended
[0].ulong_ptr
;
84 status
= io_status
->Status
;
85 } __except(EXCEPTION_EXECUTE_HANDLER
) {
91 operator delete(name
, NT_ALLOC
);
96 NTSTATUS WINAPI
TargetNtOpenFile(NtOpenFileFunction orig_OpenFile
, PHANDLE file
,
97 ACCESS_MASK desired_access
,
98 POBJECT_ATTRIBUTES object_attributes
,
99 PIO_STATUS_BLOCK io_status
, ULONG sharing
,
101 // Check if the process can open it first.
102 NTSTATUS status
= orig_OpenFile(file
, desired_access
, object_attributes
,
103 io_status
, sharing
, options
);
104 if (STATUS_ACCESS_DENIED
!= status
)
107 // We don't trust that the IPC can work this early.
108 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
111 wchar_t* name
= NULL
;
113 if (!ValidParameter(file
, sizeof(HANDLE
), WRITE
))
115 if (!ValidParameter(io_status
, sizeof(IO_STATUS_BLOCK
), WRITE
))
118 void* memory
= GetGlobalIPCMemory();
123 NTSTATUS ret
= AllocAndCopyName(object_attributes
, &name
, &attributes
,
125 if (!NT_SUCCESS(ret
) || NULL
== name
)
128 uint32 desired_access_uint32
= desired_access
;
129 uint32 options_uint32
= options
;
130 uint32 broker
= FALSE
;
131 CountedParameterSet
<OpenFile
> params
;
132 params
[OpenFile::NAME
] = ParamPickerMake(name
);
133 params
[OpenFile::ACCESS
] = ParamPickerMake(desired_access_uint32
);
134 params
[OpenFile::OPTIONS
] = ParamPickerMake(options_uint32
);
135 params
[OpenFile::BROKER
] = ParamPickerMake(broker
);
137 if (!QueryBroker(IPC_NTOPENFILE_TAG
, params
.GetBase()))
140 SharedMemIPCClient
ipc(memory
);
141 CrossCallReturn answer
= {0};
142 ResultCode code
= CrossCall(ipc
, IPC_NTOPENFILE_TAG
, name
, attributes
,
143 desired_access_uint32
, sharing
, options_uint32
,
145 if (SBOX_ALL_OK
!= code
)
148 if (!NT_SUCCESS(answer
.nt_status
))
149 return answer
.nt_status
;
152 *file
= answer
.handle
;
153 io_status
->Status
= answer
.nt_status
;
154 io_status
->Information
= answer
.extended
[0].ulong_ptr
;
155 status
= io_status
->Status
;
156 } __except(EXCEPTION_EXECUTE_HANDLER
) {
162 operator delete(name
, NT_ALLOC
);
167 NTSTATUS WINAPI
TargetNtQueryAttributesFile(
168 NtQueryAttributesFileFunction orig_QueryAttributes
,
169 POBJECT_ATTRIBUTES object_attributes
,
170 PFILE_BASIC_INFORMATION file_attributes
) {
171 // Check if the process can query it first.
172 NTSTATUS status
= orig_QueryAttributes(object_attributes
, file_attributes
);
173 if (STATUS_ACCESS_DENIED
!= status
)
176 // We don't trust that the IPC can work this early.
177 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
180 wchar_t* name
= NULL
;
182 if (!ValidParameter(file_attributes
, sizeof(FILE_BASIC_INFORMATION
), WRITE
))
185 void* memory
= GetGlobalIPCMemory();
189 uint32 attributes
= 0;
190 NTSTATUS ret
= AllocAndCopyName(object_attributes
, &name
, &attributes
,
192 if (!NT_SUCCESS(ret
) || NULL
== name
)
195 InOutCountedBuffer
file_info(file_attributes
,
196 sizeof(FILE_BASIC_INFORMATION
));
198 uint32 broker
= FALSE
;
199 CountedParameterSet
<FileName
> params
;
200 params
[FileName::NAME
] = ParamPickerMake(name
);
201 params
[FileName::BROKER
] = ParamPickerMake(broker
);
203 if (!QueryBroker(IPC_NTQUERYATTRIBUTESFILE_TAG
, params
.GetBase()))
206 SharedMemIPCClient
ipc(memory
);
207 CrossCallReturn answer
= {0};
208 ResultCode code
= CrossCall(ipc
, IPC_NTQUERYATTRIBUTESFILE_TAG
, name
,
209 attributes
, file_info
, &answer
);
211 operator delete(name
, NT_ALLOC
);
213 if (SBOX_ALL_OK
!= code
)
216 return answer
.nt_status
;
221 operator delete(name
, NT_ALLOC
);
226 NTSTATUS WINAPI
TargetNtQueryFullAttributesFile(
227 NtQueryFullAttributesFileFunction orig_QueryFullAttributes
,
228 POBJECT_ATTRIBUTES object_attributes
,
229 PFILE_NETWORK_OPEN_INFORMATION file_attributes
) {
230 // Check if the process can query it first.
231 NTSTATUS status
= orig_QueryFullAttributes(object_attributes
,
233 if (STATUS_ACCESS_DENIED
!= status
)
236 // We don't trust that the IPC can work this early.
237 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
240 wchar_t* name
= NULL
;
242 if (!ValidParameter(file_attributes
, sizeof(FILE_NETWORK_OPEN_INFORMATION
),
246 void* memory
= GetGlobalIPCMemory();
250 uint32 attributes
= 0;
251 NTSTATUS ret
= AllocAndCopyName(object_attributes
, &name
, &attributes
,
253 if (!NT_SUCCESS(ret
) || NULL
== name
)
256 InOutCountedBuffer
file_info(file_attributes
,
257 sizeof(FILE_NETWORK_OPEN_INFORMATION
));
259 uint32 broker
= FALSE
;
260 CountedParameterSet
<FileName
> params
;
261 params
[FileName::NAME
] = ParamPickerMake(name
);
262 params
[FileName::BROKER
] = ParamPickerMake(broker
);
264 if (!QueryBroker(IPC_NTQUERYFULLATTRIBUTESFILE_TAG
, params
.GetBase()))
267 SharedMemIPCClient
ipc(memory
);
268 CrossCallReturn answer
= {0};
269 ResultCode code
= CrossCall(ipc
, IPC_NTQUERYFULLATTRIBUTESFILE_TAG
, name
,
270 attributes
, file_info
, &answer
);
272 operator delete(name
, NT_ALLOC
);
274 if (SBOX_ALL_OK
!= code
)
277 return answer
.nt_status
;
281 operator delete(name
, NT_ALLOC
);
286 NTSTATUS WINAPI
TargetNtSetInformationFile(
287 NtSetInformationFileFunction orig_SetInformationFile
, HANDLE file
,
288 PIO_STATUS_BLOCK io_status
, PVOID file_info
, ULONG length
,
289 FILE_INFORMATION_CLASS file_info_class
) {
290 // Check if the process can open it first.
291 NTSTATUS status
= orig_SetInformationFile(file
, io_status
, file_info
, length
,
293 if (STATUS_ACCESS_DENIED
!= status
)
296 // We don't trust that the IPC can work this early.
297 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
300 wchar_t* name
= NULL
;
302 void* memory
= GetGlobalIPCMemory();
306 if (!ValidParameter(io_status
, sizeof(IO_STATUS_BLOCK
), WRITE
))
309 if (!ValidParameter(file_info
, length
, READ
))
312 FILE_RENAME_INFORMATION
* file_rename_info
=
313 reinterpret_cast<FILE_RENAME_INFORMATION
*>(file_info
);
314 OBJECT_ATTRIBUTES object_attributes
;
315 UNICODE_STRING object_name
;
316 InitializeObjectAttributes(&object_attributes
, &object_name
, 0, NULL
, NULL
);
319 if (!IsSupportedRenameCall(file_rename_info
, length
, file_info_class
))
322 object_attributes
.RootDirectory
= file_rename_info
->RootDirectory
;
323 object_name
.Buffer
= file_rename_info
->FileName
;
324 object_name
.Length
= object_name
.MaximumLength
=
325 static_cast<USHORT
>(file_rename_info
->FileNameLength
);
326 } __except(EXCEPTION_EXECUTE_HANDLER
) {
330 NTSTATUS ret
= AllocAndCopyName(&object_attributes
, &name
, NULL
, NULL
);
331 if (!NT_SUCCESS(ret
) || !name
)
334 uint32 broker
= FALSE
;
335 CountedParameterSet
<FileName
> params
;
336 params
[FileName::NAME
] = ParamPickerMake(name
);
337 params
[FileName::BROKER
] = ParamPickerMake(broker
);
339 if (!QueryBroker(IPC_NTSETINFO_RENAME_TAG
, params
.GetBase()))
342 InOutCountedBuffer
io_status_buffer(io_status
, sizeof(IO_STATUS_BLOCK
));
343 // This is actually not an InOut buffer, only In, but using InOut facility
344 // really helps to simplify the code.
345 InOutCountedBuffer
file_info_buffer(file_info
, length
);
347 SharedMemIPCClient
ipc(memory
);
348 CrossCallReturn answer
= {0};
349 ResultCode code
= CrossCall(ipc
, IPC_NTSETINFO_RENAME_TAG
, file
,
350 io_status_buffer
, file_info_buffer
, length
,
351 file_info_class
, &answer
);
353 if (SBOX_ALL_OK
!= code
)
356 status
= answer
.nt_status
;
360 operator delete(name
, NT_ALLOC
);
365 } // namespace sandbox