• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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