OLD | NEW |
| (Empty) |
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/src/filesystem_interception.h" | |
6 | |
7 #include "sandbox/src/crosscall_client.h" | |
8 #include "sandbox/src/ipc_tags.h" | |
9 #include "sandbox/src/policy_params.h" | |
10 #include "sandbox/src/policy_target.h" | |
11 #include "sandbox/src/sandbox_factory.h" | |
12 #include "sandbox/src/sandbox_nt_util.h" | |
13 #include "sandbox/src/sharedmem_ipc_client.h" | |
14 #include "sandbox/src/target_services.h" | |
15 | |
16 namespace sandbox { | |
17 | |
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 | |
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 | |
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 | |
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 | |
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 | |
OLD | NEW |