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::OPTIONS
] = ParamPickerMake(create_options
);
106 params
[OpenFile::BROKER
] = ParamPickerMake(broker
);
108 // To evaluate the policy we need to call back to the policy object. We
109 // are just middlemen in the operation since is the FileSystemPolicy which
111 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTCREATEFILE_TAG
,
114 ULONG_PTR io_information
= 0;
116 if (!FileSystemPolicy::CreateFileAction(result
, *ipc
->client_info
, *name
,
117 attributes
, desired_access
,
118 file_attributes
, share_access
,
119 create_disposition
, create_options
,
122 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
125 // Return operation status on the IPC.
126 ipc
->return_info
.extended
[0].ulong_ptr
= io_information
;
127 ipc
->return_info
.nt_status
= nt_status
;
128 ipc
->return_info
.handle
= handle
;
132 bool FilesystemDispatcher::NtOpenFile(IPCInfo
* ipc
,
133 base::string16
* name
,
135 uint32 desired_access
,
137 uint32 open_options
) {
138 if (!PreProcessName(*name
, name
)) {
139 // The path requested might contain a reparse point.
140 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
144 const wchar_t* filename
= name
->c_str();
146 uint32 broker
= TRUE
;
147 CountedParameterSet
<OpenFile
> params
;
148 params
[OpenFile::NAME
] = ParamPickerMake(filename
);
149 params
[OpenFile::ACCESS
] = ParamPickerMake(desired_access
);
150 params
[OpenFile::OPTIONS
] = ParamPickerMake(open_options
);
151 params
[OpenFile::BROKER
] = ParamPickerMake(broker
);
153 // To evaluate the policy we need to call back to the policy object. We
154 // are just middlemen in the operation since is the FileSystemPolicy which
156 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTOPENFILE_TAG
,
159 ULONG_PTR io_information
= 0;
161 if (!FileSystemPolicy::OpenFileAction(result
, *ipc
->client_info
, *name
,
162 attributes
, desired_access
,
163 share_access
, open_options
, &handle
,
164 &nt_status
, &io_information
)) {
165 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
168 // Return operation status on the IPC.
169 ipc
->return_info
.extended
[0].ulong_ptr
= io_information
;
170 ipc
->return_info
.nt_status
= nt_status
;
171 ipc
->return_info
.handle
= handle
;
175 bool FilesystemDispatcher::NtQueryAttributesFile(IPCInfo
* ipc
,
176 base::string16
* name
,
178 CountedBuffer
* info
) {
179 if (sizeof(FILE_BASIC_INFORMATION
) != info
->Size())
182 if (!PreProcessName(*name
, name
)) {
183 // The path requested might contain a reparse point.
184 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
188 uint32 broker
= TRUE
;
189 const wchar_t* filename
= name
->c_str();
190 CountedParameterSet
<FileName
> params
;
191 params
[FileName::NAME
] = ParamPickerMake(filename
);
192 params
[FileName::BROKER
] = ParamPickerMake(broker
);
194 // To evaluate the policy we need to call back to the policy object. We
195 // are just middlemen in the operation since is the FileSystemPolicy which
197 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTQUERYATTRIBUTESFILE_TAG
,
200 FILE_BASIC_INFORMATION
* information
=
201 reinterpret_cast<FILE_BASIC_INFORMATION
*>(info
->Buffer());
203 if (!FileSystemPolicy::QueryAttributesFileAction(result
, *ipc
->client_info
,
205 information
, &nt_status
)) {
206 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
210 // Return operation status on the IPC.
211 ipc
->return_info
.nt_status
= nt_status
;
215 bool FilesystemDispatcher::NtQueryFullAttributesFile(IPCInfo
* ipc
,
216 base::string16
* name
,
218 CountedBuffer
* info
) {
219 if (sizeof(FILE_NETWORK_OPEN_INFORMATION
) != info
->Size())
222 if (!PreProcessName(*name
, name
)) {
223 // The path requested might contain a reparse point.
224 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
228 uint32 broker
= TRUE
;
229 const wchar_t* filename
= name
->c_str();
230 CountedParameterSet
<FileName
> params
;
231 params
[FileName::NAME
] = ParamPickerMake(filename
);
232 params
[FileName::BROKER
] = ParamPickerMake(broker
);
234 // To evaluate the policy we need to call back to the policy object. We
235 // are just middlemen in the operation since is the FileSystemPolicy which
237 EvalResult result
= policy_base_
->EvalPolicy(
238 IPC_NTQUERYFULLATTRIBUTESFILE_TAG
, params
.GetBase());
240 FILE_NETWORK_OPEN_INFORMATION
* information
=
241 reinterpret_cast<FILE_NETWORK_OPEN_INFORMATION
*>(info
->Buffer());
243 if (!FileSystemPolicy::QueryFullAttributesFileAction(result
,
248 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
252 // Return operation status on the IPC.
253 ipc
->return_info
.nt_status
= nt_status
;
257 bool FilesystemDispatcher::NtSetInformationFile(IPCInfo
* ipc
,
259 CountedBuffer
* status
,
263 if (sizeof(IO_STATUS_BLOCK
) != status
->Size())
265 if (length
!= info
->Size())
268 FILE_RENAME_INFORMATION
* rename_info
=
269 reinterpret_cast<FILE_RENAME_INFORMATION
*>(info
->Buffer());
271 if (!IsSupportedRenameCall(rename_info
, length
, info_class
))
275 name
.assign(rename_info
->FileName
, rename_info
->FileNameLength
/
276 sizeof(rename_info
->FileName
[0]));
277 if (!PreProcessName(name
, &name
)) {
278 // The path requested might contain a reparse point.
279 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
283 uint32 broker
= TRUE
;
284 const wchar_t* filename
= name
.c_str();
285 CountedParameterSet
<FileName
> params
;
286 params
[FileName::NAME
] = ParamPickerMake(filename
);
287 params
[FileName::BROKER
] = ParamPickerMake(broker
);
289 // To evaluate the policy we need to call back to the policy object. We
290 // are just middlemen in the operation since is the FileSystemPolicy which
292 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTSETINFO_RENAME_TAG
,
295 IO_STATUS_BLOCK
* io_status
=
296 reinterpret_cast<IO_STATUS_BLOCK
*>(status
->Buffer());
298 if (!FileSystemPolicy::SetInformationFileAction(result
, *ipc
->client_info
,
299 handle
, rename_info
, length
,
300 info_class
, io_status
,
302 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
306 // Return operation status on the IPC.
307 ipc
->return_info
.nt_status
= nt_status
;
311 } // namespace sandbox