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/win/src/filesystem_interception.h"
6
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"
15
16 namespace sandbox {
17
TargetNtCreateFile(NtCreateFileFunction orig_CreateFile,PHANDLE file,ACCESS_MASK desired_access,POBJECT_ATTRIBUTES object_attributes,PIO_STATUS_BLOCK io_status,PLARGE_INTEGER allocation_size,ULONG file_attributes,ULONG sharing,ULONG disposition,ULONG options,PVOID ea_buffer,ULONG ea_length)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
TargetNtOpenFile(NtOpenFileFunction orig_OpenFile,PHANDLE file,ACCESS_MASK desired_access,POBJECT_ATTRIBUTES object_attributes,PIO_STATUS_BLOCK io_status,ULONG sharing,ULONG options)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
TargetNtQueryAttributesFile(NtQueryAttributesFileFunction orig_QueryAttributes,POBJECT_ATTRIBUTES object_attributes,PFILE_BASIC_INFORMATION file_attributes)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
TargetNtQueryFullAttributesFile(NtQueryFullAttributesFileFunction orig_QueryFullAttributes,POBJECT_ATTRIBUTES object_attributes,PFILE_NETWORK_OPEN_INFORMATION file_attributes)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
TargetNtSetInformationFile(NtSetInformationFileFunction orig_SetInformationFile,HANDLE file,PIO_STATUS_BLOCK io_status,PVOID file_info,ULONG length,FILE_INFORMATION_CLASS file_info_class)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
352