1 // Copyright (c) 2006-2010 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_dispatcher.h"
7 #include "sandbox/win/src/crosscall_client.h"
8 #include "sandbox/win/src/filesystem_interception.h"
9 #include "sandbox/win/src/filesystem_policy.h"
10 #include "sandbox/win/src/interception.h"
11 #include "sandbox/win/src/interceptors.h"
12 #include "sandbox/win/src/ipc_tags.h"
13 #include "sandbox/win/src/policy_broker.h"
14 #include "sandbox/win/src/policy_params.h"
15 #include "sandbox/win/src/sandbox.h"
16 #include "sandbox/win/src/sandbox_nt_util.h"
20 FilesystemDispatcher::FilesystemDispatcher(PolicyBase
* policy_base
)
21 : policy_base_(policy_base
) {
22 static const IPCCall create_params
= {
23 {IPC_NTCREATEFILE_TAG
, WCHAR_TYPE
, UINT32_TYPE
, UINT32_TYPE
, UINT32_TYPE
,
24 UINT32_TYPE
, UINT32_TYPE
, UINT32_TYPE
},
25 reinterpret_cast<CallbackGeneric
>(&FilesystemDispatcher::NtCreateFile
)
28 static const IPCCall open_file
= {
29 {IPC_NTOPENFILE_TAG
, WCHAR_TYPE
, UINT32_TYPE
, UINT32_TYPE
, UINT32_TYPE
,
31 reinterpret_cast<CallbackGeneric
>(&FilesystemDispatcher::NtOpenFile
)
34 static const IPCCall attribs
= {
35 {IPC_NTQUERYATTRIBUTESFILE_TAG
, WCHAR_TYPE
, UINT32_TYPE
, INOUTPTR_TYPE
},
36 reinterpret_cast<CallbackGeneric
>(
37 &FilesystemDispatcher::NtQueryAttributesFile
)
40 static const IPCCall full_attribs
= {
41 {IPC_NTQUERYFULLATTRIBUTESFILE_TAG
, WCHAR_TYPE
, UINT32_TYPE
, INOUTPTR_TYPE
},
42 reinterpret_cast<CallbackGeneric
>(
43 &FilesystemDispatcher::NtQueryFullAttributesFile
)
46 static const IPCCall set_info
= {
47 {IPC_NTSETINFO_RENAME_TAG
, VOIDPTR_TYPE
, INOUTPTR_TYPE
, INOUTPTR_TYPE
,
48 UINT32_TYPE
, UINT32_TYPE
},
49 reinterpret_cast<CallbackGeneric
>(
50 &FilesystemDispatcher::NtSetInformationFile
)
53 ipc_calls_
.push_back(create_params
);
54 ipc_calls_
.push_back(open_file
);
55 ipc_calls_
.push_back(attribs
);
56 ipc_calls_
.push_back(full_attribs
);
57 ipc_calls_
.push_back(set_info
);
60 bool FilesystemDispatcher::SetupService(InterceptionManager
* manager
,
63 case IPC_NTCREATEFILE_TAG
:
64 return INTERCEPT_NT(manager
, NtCreateFile
, CREATE_FILE_ID
, 48);
66 case IPC_NTOPENFILE_TAG
:
67 return INTERCEPT_NT(manager
, NtOpenFile
, OPEN_FILE_ID
, 28);
69 case IPC_NTQUERYATTRIBUTESFILE_TAG
:
70 return INTERCEPT_NT(manager
, NtQueryAttributesFile
, QUERY_ATTRIB_FILE_ID
,
73 case IPC_NTQUERYFULLATTRIBUTESFILE_TAG
:
74 return INTERCEPT_NT(manager
, NtQueryFullAttributesFile
,
75 QUERY_FULL_ATTRIB_FILE_ID
, 12);
77 case IPC_NTSETINFO_RENAME_TAG
:
78 return INTERCEPT_NT(manager
, NtSetInformationFile
, SET_INFO_FILE_ID
, 24);
85 bool FilesystemDispatcher::NtCreateFile(IPCInfo
* ipc
,
88 uint32 desired_access
,
89 uint32 file_attributes
,
91 uint32 create_disposition
,
92 uint32 create_options
) {
93 if (!PreProcessName(*name
, name
)) {
94 // The path requested might contain a reparse point.
95 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
99 const wchar_t* filename
= name
->c_str();
101 uint32 broker
= TRUE
;
102 CountedParameterSet
<OpenFile
> params
;
103 params
[OpenFile::NAME
] = ParamPickerMake(filename
);
104 params
[OpenFile::ACCESS
] = ParamPickerMake(desired_access
);
105 params
[OpenFile::DISPOSITION
] = ParamPickerMake(create_disposition
);
106 params
[OpenFile::OPTIONS
] = ParamPickerMake(create_options
);
107 params
[OpenFile::BROKER
] = ParamPickerMake(broker
);
109 // To evaluate the policy we need to call back to the policy object. We
110 // are just middlemen in the operation since is the FileSystemPolicy which
112 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTCREATEFILE_TAG
,
115 ULONG_PTR io_information
= 0;
117 if (!FileSystemPolicy::CreateFileAction(result
, *ipc
->client_info
, *name
,
118 attributes
, desired_access
,
119 file_attributes
, share_access
,
120 create_disposition
, create_options
,
123 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
126 // Return operation status on the IPC.
127 ipc
->return_info
.extended
[0].ulong_ptr
= io_information
;
128 ipc
->return_info
.nt_status
= nt_status
;
129 ipc
->return_info
.handle
= handle
;
133 bool FilesystemDispatcher::NtOpenFile(IPCInfo
* ipc
,
134 base::string16
* name
,
136 uint32 desired_access
,
138 uint32 open_options
) {
139 if (!PreProcessName(*name
, name
)) {
140 // The path requested might contain a reparse point.
141 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
145 const wchar_t* filename
= name
->c_str();
147 uint32 broker
= TRUE
;
148 uint32 create_disposition
= FILE_OPEN
;
149 CountedParameterSet
<OpenFile
> params
;
150 params
[OpenFile::NAME
] = ParamPickerMake(filename
);
151 params
[OpenFile::ACCESS
] = ParamPickerMake(desired_access
);
152 params
[OpenFile::DISPOSITION
] = ParamPickerMake(create_disposition
);
153 params
[OpenFile::OPTIONS
] = ParamPickerMake(open_options
);
154 params
[OpenFile::BROKER
] = ParamPickerMake(broker
);
156 // To evaluate the policy we need to call back to the policy object. We
157 // are just middlemen in the operation since is the FileSystemPolicy which
159 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTOPENFILE_TAG
,
162 ULONG_PTR io_information
= 0;
164 if (!FileSystemPolicy::OpenFileAction(result
, *ipc
->client_info
, *name
,
165 attributes
, desired_access
,
166 share_access
, open_options
, &handle
,
167 &nt_status
, &io_information
)) {
168 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
171 // Return operation status on the IPC.
172 ipc
->return_info
.extended
[0].ulong_ptr
= io_information
;
173 ipc
->return_info
.nt_status
= nt_status
;
174 ipc
->return_info
.handle
= handle
;
178 bool FilesystemDispatcher::NtQueryAttributesFile(IPCInfo
* ipc
,
179 base::string16
* name
,
181 CountedBuffer
* info
) {
182 if (sizeof(FILE_BASIC_INFORMATION
) != info
->Size())
185 if (!PreProcessName(*name
, name
)) {
186 // The path requested might contain a reparse point.
187 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
191 uint32 broker
= TRUE
;
192 const wchar_t* filename
= name
->c_str();
193 CountedParameterSet
<FileName
> params
;
194 params
[FileName::NAME
] = ParamPickerMake(filename
);
195 params
[FileName::BROKER
] = ParamPickerMake(broker
);
197 // To evaluate the policy we need to call back to the policy object. We
198 // are just middlemen in the operation since is the FileSystemPolicy which
200 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTQUERYATTRIBUTESFILE_TAG
,
203 FILE_BASIC_INFORMATION
* information
=
204 reinterpret_cast<FILE_BASIC_INFORMATION
*>(info
->Buffer());
206 if (!FileSystemPolicy::QueryAttributesFileAction(result
, *ipc
->client_info
,
208 information
, &nt_status
)) {
209 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
213 // Return operation status on the IPC.
214 ipc
->return_info
.nt_status
= nt_status
;
218 bool FilesystemDispatcher::NtQueryFullAttributesFile(IPCInfo
* ipc
,
219 base::string16
* name
,
221 CountedBuffer
* info
) {
222 if (sizeof(FILE_NETWORK_OPEN_INFORMATION
) != info
->Size())
225 if (!PreProcessName(*name
, name
)) {
226 // The path requested might contain a reparse point.
227 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
231 uint32 broker
= TRUE
;
232 const wchar_t* filename
= name
->c_str();
233 CountedParameterSet
<FileName
> params
;
234 params
[FileName::NAME
] = ParamPickerMake(filename
);
235 params
[FileName::BROKER
] = ParamPickerMake(broker
);
237 // To evaluate the policy we need to call back to the policy object. We
238 // are just middlemen in the operation since is the FileSystemPolicy which
240 EvalResult result
= policy_base_
->EvalPolicy(
241 IPC_NTQUERYFULLATTRIBUTESFILE_TAG
, params
.GetBase());
243 FILE_NETWORK_OPEN_INFORMATION
* information
=
244 reinterpret_cast<FILE_NETWORK_OPEN_INFORMATION
*>(info
->Buffer());
246 if (!FileSystemPolicy::QueryFullAttributesFileAction(result
,
251 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
255 // Return operation status on the IPC.
256 ipc
->return_info
.nt_status
= nt_status
;
260 bool FilesystemDispatcher::NtSetInformationFile(IPCInfo
* ipc
,
262 CountedBuffer
* status
,
266 if (sizeof(IO_STATUS_BLOCK
) != status
->Size())
268 if (length
!= info
->Size())
271 FILE_RENAME_INFORMATION
* rename_info
=
272 reinterpret_cast<FILE_RENAME_INFORMATION
*>(info
->Buffer());
274 if (!IsSupportedRenameCall(rename_info
, length
, info_class
))
278 name
.assign(rename_info
->FileName
, rename_info
->FileNameLength
/
279 sizeof(rename_info
->FileName
[0]));
280 if (!PreProcessName(name
, &name
)) {
281 // The path requested might contain a reparse point.
282 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
286 uint32 broker
= TRUE
;
287 const wchar_t* filename
= name
.c_str();
288 CountedParameterSet
<FileName
> params
;
289 params
[FileName::NAME
] = ParamPickerMake(filename
);
290 params
[FileName::BROKER
] = ParamPickerMake(broker
);
292 // To evaluate the policy we need to call back to the policy object. We
293 // are just middlemen in the operation since is the FileSystemPolicy which
295 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTSETINFO_RENAME_TAG
,
298 IO_STATUS_BLOCK
* io_status
=
299 reinterpret_cast<IO_STATUS_BLOCK
*>(status
->Buffer());
301 if (!FileSystemPolicy::SetInformationFileAction(result
, *ipc
->client_info
,
302 handle
, rename_info
, length
,
303 info_class
, io_status
,
305 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
309 // Return operation status on the IPC.
310 ipc
->return_info
.nt_status
= nt_status
;
314 } // namespace sandbox