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
,
31 reinterpret_cast<CallbackGeneric
>(&FilesystemDispatcher::NtCreateFile
)};
33 static const IPCCall open_file
= {
35 {WCHAR_TYPE
, UINT32_TYPE
, UINT32_TYPE
, UINT32_TYPE
, UINT32_TYPE
}},
36 reinterpret_cast<CallbackGeneric
>(&FilesystemDispatcher::NtOpenFile
)};
38 static const IPCCall attribs
= {
39 {IPC_NTQUERYATTRIBUTESFILE_TAG
, {WCHAR_TYPE
, UINT32_TYPE
, INOUTPTR_TYPE
}},
40 reinterpret_cast<CallbackGeneric
>(
41 &FilesystemDispatcher::NtQueryAttributesFile
)};
43 static const IPCCall full_attribs
= {
44 {IPC_NTQUERYFULLATTRIBUTESFILE_TAG
,
45 {WCHAR_TYPE
, UINT32_TYPE
, INOUTPTR_TYPE
}},
46 reinterpret_cast<CallbackGeneric
>(
47 &FilesystemDispatcher::NtQueryFullAttributesFile
)};
49 static const IPCCall set_info
= {
50 {IPC_NTSETINFO_RENAME_TAG
,
51 {VOIDPTR_TYPE
, INOUTPTR_TYPE
, INOUTPTR_TYPE
, UINT32_TYPE
, UINT32_TYPE
}},
52 reinterpret_cast<CallbackGeneric
>(
53 &FilesystemDispatcher::NtSetInformationFile
)};
55 ipc_calls_
.push_back(create_params
);
56 ipc_calls_
.push_back(open_file
);
57 ipc_calls_
.push_back(attribs
);
58 ipc_calls_
.push_back(full_attribs
);
59 ipc_calls_
.push_back(set_info
);
62 bool FilesystemDispatcher::SetupService(InterceptionManager
* manager
,
65 case IPC_NTCREATEFILE_TAG
:
66 return INTERCEPT_NT(manager
, NtCreateFile
, CREATE_FILE_ID
, 48);
68 case IPC_NTOPENFILE_TAG
:
69 return INTERCEPT_NT(manager
, NtOpenFile
, OPEN_FILE_ID
, 28);
71 case IPC_NTQUERYATTRIBUTESFILE_TAG
:
72 return INTERCEPT_NT(manager
, NtQueryAttributesFile
, QUERY_ATTRIB_FILE_ID
,
75 case IPC_NTQUERYFULLATTRIBUTESFILE_TAG
:
76 return INTERCEPT_NT(manager
, NtQueryFullAttributesFile
,
77 QUERY_FULL_ATTRIB_FILE_ID
, 12);
79 case IPC_NTSETINFO_RENAME_TAG
:
80 return INTERCEPT_NT(manager
, NtSetInformationFile
, SET_INFO_FILE_ID
, 24);
87 bool FilesystemDispatcher::NtCreateFile(IPCInfo
* ipc
,
90 uint32 desired_access
,
91 uint32 file_attributes
,
93 uint32 create_disposition
,
94 uint32 create_options
) {
95 if (!PreProcessName(name
)) {
96 // The path requested might contain a reparse point.
97 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
101 const wchar_t* filename
= name
->c_str();
103 uint32 broker
= TRUE
;
104 CountedParameterSet
<OpenFile
> params
;
105 params
[OpenFile::NAME
] = ParamPickerMake(filename
);
106 params
[OpenFile::ACCESS
] = ParamPickerMake(desired_access
);
107 params
[OpenFile::DISPOSITION
] = ParamPickerMake(create_disposition
);
108 params
[OpenFile::OPTIONS
] = ParamPickerMake(create_options
);
109 params
[OpenFile::BROKER
] = ParamPickerMake(broker
);
111 // To evaluate the policy we need to call back to the policy object. We
112 // are just middlemen in the operation since is the FileSystemPolicy which
114 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTCREATEFILE_TAG
,
117 ULONG_PTR io_information
= 0;
119 if (!FileSystemPolicy::CreateFileAction(result
, *ipc
->client_info
, *name
,
120 attributes
, desired_access
,
121 file_attributes
, share_access
,
122 create_disposition
, create_options
,
125 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
128 // Return operation status on the IPC.
129 ipc
->return_info
.extended
[0].ulong_ptr
= io_information
;
130 ipc
->return_info
.nt_status
= nt_status
;
131 ipc
->return_info
.handle
= handle
;
135 bool FilesystemDispatcher::NtOpenFile(IPCInfo
* ipc
,
136 base::string16
* name
,
138 uint32 desired_access
,
140 uint32 open_options
) {
141 if (!PreProcessName(name
)) {
142 // The path requested might contain a reparse point.
143 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
147 const wchar_t* filename
= name
->c_str();
149 uint32 broker
= TRUE
;
150 uint32 create_disposition
= FILE_OPEN
;
151 CountedParameterSet
<OpenFile
> params
;
152 params
[OpenFile::NAME
] = ParamPickerMake(filename
);
153 params
[OpenFile::ACCESS
] = ParamPickerMake(desired_access
);
154 params
[OpenFile::DISPOSITION
] = ParamPickerMake(create_disposition
);
155 params
[OpenFile::OPTIONS
] = ParamPickerMake(open_options
);
156 params
[OpenFile::BROKER
] = ParamPickerMake(broker
);
158 // To evaluate the policy we need to call back to the policy object. We
159 // are just middlemen in the operation since is the FileSystemPolicy which
161 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTOPENFILE_TAG
,
164 ULONG_PTR io_information
= 0;
166 if (!FileSystemPolicy::OpenFileAction(result
, *ipc
->client_info
, *name
,
167 attributes
, desired_access
,
168 share_access
, open_options
, &handle
,
169 &nt_status
, &io_information
)) {
170 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
173 // Return operation status on the IPC.
174 ipc
->return_info
.extended
[0].ulong_ptr
= io_information
;
175 ipc
->return_info
.nt_status
= nt_status
;
176 ipc
->return_info
.handle
= handle
;
180 bool FilesystemDispatcher::NtQueryAttributesFile(IPCInfo
* ipc
,
181 base::string16
* name
,
183 CountedBuffer
* info
) {
184 if (sizeof(FILE_BASIC_INFORMATION
) != info
->Size())
187 if (!PreProcessName(name
)) {
188 // The path requested might contain a reparse point.
189 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
193 uint32 broker
= TRUE
;
194 const wchar_t* filename
= name
->c_str();
195 CountedParameterSet
<FileName
> params
;
196 params
[FileName::NAME
] = ParamPickerMake(filename
);
197 params
[FileName::BROKER
] = ParamPickerMake(broker
);
199 // To evaluate the policy we need to call back to the policy object. We
200 // are just middlemen in the operation since is the FileSystemPolicy which
202 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTQUERYATTRIBUTESFILE_TAG
,
205 FILE_BASIC_INFORMATION
* information
=
206 reinterpret_cast<FILE_BASIC_INFORMATION
*>(info
->Buffer());
208 if (!FileSystemPolicy::QueryAttributesFileAction(result
, *ipc
->client_info
,
210 information
, &nt_status
)) {
211 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
215 // Return operation status on the IPC.
216 ipc
->return_info
.nt_status
= nt_status
;
220 bool FilesystemDispatcher::NtQueryFullAttributesFile(IPCInfo
* ipc
,
221 base::string16
* name
,
223 CountedBuffer
* info
) {
224 if (sizeof(FILE_NETWORK_OPEN_INFORMATION
) != info
->Size())
227 if (!PreProcessName(name
)) {
228 // The path requested might contain a reparse point.
229 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
233 uint32 broker
= TRUE
;
234 const wchar_t* filename
= name
->c_str();
235 CountedParameterSet
<FileName
> params
;
236 params
[FileName::NAME
] = ParamPickerMake(filename
);
237 params
[FileName::BROKER
] = ParamPickerMake(broker
);
239 // To evaluate the policy we need to call back to the policy object. We
240 // are just middlemen in the operation since is the FileSystemPolicy which
242 EvalResult result
= policy_base_
->EvalPolicy(
243 IPC_NTQUERYFULLATTRIBUTESFILE_TAG
, params
.GetBase());
245 FILE_NETWORK_OPEN_INFORMATION
* information
=
246 reinterpret_cast<FILE_NETWORK_OPEN_INFORMATION
*>(info
->Buffer());
248 if (!FileSystemPolicy::QueryFullAttributesFileAction(result
,
253 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
257 // Return operation status on the IPC.
258 ipc
->return_info
.nt_status
= nt_status
;
262 bool FilesystemDispatcher::NtSetInformationFile(IPCInfo
* ipc
,
264 CountedBuffer
* status
,
268 if (sizeof(IO_STATUS_BLOCK
) != status
->Size())
270 if (length
!= info
->Size())
273 FILE_RENAME_INFORMATION
* rename_info
=
274 reinterpret_cast<FILE_RENAME_INFORMATION
*>(info
->Buffer());
276 if (!IsSupportedRenameCall(rename_info
, length
, info_class
))
280 name
.assign(rename_info
->FileName
, rename_info
->FileNameLength
/
281 sizeof(rename_info
->FileName
[0]));
282 if (!PreProcessName(&name
)) {
283 // The path requested might contain a reparse point.
284 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
288 uint32 broker
= TRUE
;
289 const wchar_t* filename
= name
.c_str();
290 CountedParameterSet
<FileName
> params
;
291 params
[FileName::NAME
] = ParamPickerMake(filename
);
292 params
[FileName::BROKER
] = ParamPickerMake(broker
);
294 // To evaluate the policy we need to call back to the policy object. We
295 // are just middlemen in the operation since is the FileSystemPolicy which
297 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTSETINFO_RENAME_TAG
,
300 IO_STATUS_BLOCK
* io_status
=
301 reinterpret_cast<IO_STATUS_BLOCK
*>(status
->Buffer());
303 if (!FileSystemPolicy::SetInformationFileAction(result
, *ipc
->client_info
,
304 handle
, rename_info
, length
,
305 info_class
, io_status
,
307 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
311 // Return operation status on the IPC.
312 ipc
->return_info
.nt_status
= nt_status
;
316 } // namespace sandbox