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
, ULONG_TYPE
, ULONG_TYPE
, ULONG_TYPE
,
24 ULONG_TYPE
, ULONG_TYPE
, ULONG_TYPE
},
25 reinterpret_cast<CallbackGeneric
>(&FilesystemDispatcher::NtCreateFile
)
28 static const IPCCall open_file
= {
29 {IPC_NTOPENFILE_TAG
, WCHAR_TYPE
, ULONG_TYPE
, ULONG_TYPE
, ULONG_TYPE
,
31 reinterpret_cast<CallbackGeneric
>(&FilesystemDispatcher::NtOpenFile
)
34 static const IPCCall attribs
= {
35 {IPC_NTQUERYATTRIBUTESFILE_TAG
, WCHAR_TYPE
, ULONG_TYPE
, INOUTPTR_TYPE
},
36 reinterpret_cast<CallbackGeneric
>(
37 &FilesystemDispatcher::NtQueryAttributesFile
)
40 static const IPCCall full_attribs
= {
41 {IPC_NTQUERYFULLATTRIBUTESFILE_TAG
, WCHAR_TYPE
, ULONG_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 ULONG_TYPE
, ULONG_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(
86 IPCInfo
* ipc
, std::wstring
* name
, DWORD attributes
, DWORD desired_access
,
87 DWORD file_attributes
, DWORD share_access
, DWORD create_disposition
,
88 DWORD create_options
) {
89 if (!PreProcessName(*name
, name
)) {
90 // The path requested might contain a reparse point.
91 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
95 const wchar_t* filename
= name
->c_str();
98 CountedParameterSet
<OpenFile
> params
;
99 params
[OpenFile::NAME
] = ParamPickerMake(filename
);
100 params
[OpenFile::ACCESS
] = ParamPickerMake(desired_access
);
101 params
[OpenFile::OPTIONS
] = ParamPickerMake(create_options
);
102 params
[OpenFile::BROKER
] = ParamPickerMake(broker
);
104 // To evaluate the policy we need to call back to the policy object. We
105 // are just middlemen in the operation since is the FileSystemPolicy which
107 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTCREATEFILE_TAG
,
110 ULONG_PTR io_information
= 0;
112 if (!FileSystemPolicy::CreateFileAction(result
, *ipc
->client_info
, *name
,
113 attributes
, desired_access
,
114 file_attributes
, share_access
,
115 create_disposition
, create_options
,
118 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
121 // Return operation status on the IPC.
122 ipc
->return_info
.extended
[0].ulong_ptr
= io_information
;
123 ipc
->return_info
.nt_status
= nt_status
;
124 ipc
->return_info
.handle
= handle
;
128 bool FilesystemDispatcher::NtOpenFile(
129 IPCInfo
* ipc
, std::wstring
* name
, DWORD attributes
, DWORD desired_access
,
130 DWORD share_access
, DWORD open_options
) {
131 if (!PreProcessName(*name
, name
)) {
132 // The path requested might contain a reparse point.
133 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
137 const wchar_t* filename
= name
->c_str();
140 CountedParameterSet
<OpenFile
> params
;
141 params
[OpenFile::NAME
] = ParamPickerMake(filename
);
142 params
[OpenFile::ACCESS
] = ParamPickerMake(desired_access
);
143 params
[OpenFile::OPTIONS
] = ParamPickerMake(open_options
);
144 params
[OpenFile::BROKER
] = ParamPickerMake(broker
);
146 // To evaluate the policy we need to call back to the policy object. We
147 // are just middlemen in the operation since is the FileSystemPolicy which
149 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTOPENFILE_TAG
,
152 ULONG_PTR io_information
= 0;
154 if (!FileSystemPolicy::OpenFileAction(result
, *ipc
->client_info
, *name
,
155 attributes
, desired_access
,
156 share_access
, open_options
, &handle
,
157 &nt_status
, &io_information
)) {
158 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
161 // Return operation status on the IPC.
162 ipc
->return_info
.extended
[0].ulong_ptr
= io_information
;
163 ipc
->return_info
.nt_status
= nt_status
;
164 ipc
->return_info
.handle
= handle
;
168 bool FilesystemDispatcher::NtQueryAttributesFile(
169 IPCInfo
* ipc
, std::wstring
* name
, DWORD attributes
, CountedBuffer
* info
) {
170 if (sizeof(FILE_BASIC_INFORMATION
) != info
->Size())
173 if (!PreProcessName(*name
, name
)) {
174 // The path requested might contain a reparse point.
175 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
180 const wchar_t* filename
= name
->c_str();
181 CountedParameterSet
<FileName
> params
;
182 params
[FileName::NAME
] = ParamPickerMake(filename
);
183 params
[FileName::BROKER
] = ParamPickerMake(broker
);
185 // To evaluate the policy we need to call back to the policy object. We
186 // are just middlemen in the operation since is the FileSystemPolicy which
188 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTQUERYATTRIBUTESFILE_TAG
,
191 FILE_BASIC_INFORMATION
* information
=
192 reinterpret_cast<FILE_BASIC_INFORMATION
*>(info
->Buffer());
194 if (!FileSystemPolicy::QueryAttributesFileAction(result
, *ipc
->client_info
,
196 information
, &nt_status
)) {
197 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
201 // Return operation status on the IPC.
202 ipc
->return_info
.nt_status
= nt_status
;
206 bool FilesystemDispatcher::NtQueryFullAttributesFile(
207 IPCInfo
* ipc
, std::wstring
* name
, DWORD attributes
, CountedBuffer
* info
) {
208 if (sizeof(FILE_NETWORK_OPEN_INFORMATION
) != info
->Size())
211 if (!PreProcessName(*name
, name
)) {
212 // The path requested might contain a reparse point.
213 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
218 const wchar_t* filename
= name
->c_str();
219 CountedParameterSet
<FileName
> params
;
220 params
[FileName::NAME
] = ParamPickerMake(filename
);
221 params
[FileName::BROKER
] = ParamPickerMake(broker
);
223 // To evaluate the policy we need to call back to the policy object. We
224 // are just middlemen in the operation since is the FileSystemPolicy which
226 EvalResult result
= policy_base_
->EvalPolicy(
227 IPC_NTQUERYFULLATTRIBUTESFILE_TAG
, params
.GetBase());
229 FILE_NETWORK_OPEN_INFORMATION
* information
=
230 reinterpret_cast<FILE_NETWORK_OPEN_INFORMATION
*>(info
->Buffer());
232 if (!FileSystemPolicy::QueryFullAttributesFileAction(result
,
237 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
241 // Return operation status on the IPC.
242 ipc
->return_info
.nt_status
= nt_status
;
246 bool FilesystemDispatcher::NtSetInformationFile(
247 IPCInfo
* ipc
, HANDLE handle
, CountedBuffer
* status
, CountedBuffer
* info
,
248 DWORD length
, DWORD info_class
) {
249 if (sizeof(IO_STATUS_BLOCK
) != status
->Size())
251 if (length
!= info
->Size())
254 FILE_RENAME_INFORMATION
* rename_info
=
255 reinterpret_cast<FILE_RENAME_INFORMATION
*>(info
->Buffer());
257 if (!IsSupportedRenameCall(rename_info
, length
, info_class
))
261 name
.assign(rename_info
->FileName
, rename_info
->FileNameLength
/
262 sizeof(rename_info
->FileName
[0]));
263 if (!PreProcessName(name
, &name
)) {
264 // The path requested might contain a reparse point.
265 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
270 const wchar_t* filename
= name
.c_str();
271 CountedParameterSet
<FileName
> params
;
272 params
[FileName::NAME
] = ParamPickerMake(filename
);
273 params
[FileName::BROKER
] = ParamPickerMake(broker
);
275 // To evaluate the policy we need to call back to the policy object. We
276 // are just middlemen in the operation since is the FileSystemPolicy which
278 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTSETINFO_RENAME_TAG
,
281 IO_STATUS_BLOCK
* io_status
=
282 reinterpret_cast<IO_STATUS_BLOCK
*>(status
->Buffer());
284 if (!FileSystemPolicy::SetInformationFileAction(result
, *ipc
->client_info
,
285 handle
, rename_info
, length
,
286 info_class
, io_status
,
288 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
292 // Return operation status on the IPC.
293 ipc
->return_info
.nt_status
= nt_status
;
297 } // namespace sandbox