| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "sandbox/win/src/filesystem_dispatcher.h" | |
| 6 | |
| 7 #include <stdint.h> | |
| 8 | |
| 9 #include "sandbox/win/src/crosscall_client.h" | |
| 10 #include "sandbox/win/src/filesystem_interception.h" | |
| 11 #include "sandbox/win/src/filesystem_policy.h" | |
| 12 #include "sandbox/win/src/interception.h" | |
| 13 #include "sandbox/win/src/interceptors.h" | |
| 14 #include "sandbox/win/src/ipc_tags.h" | |
| 15 #include "sandbox/win/src/policy_broker.h" | |
| 16 #include "sandbox/win/src/policy_params.h" | |
| 17 #include "sandbox/win/src/sandbox.h" | |
| 18 #include "sandbox/win/src/sandbox_nt_util.h" | |
| 19 | |
| 20 namespace sandbox { | |
| 21 | |
| 22 FilesystemDispatcher::FilesystemDispatcher(PolicyBase* policy_base) | |
| 23 : policy_base_(policy_base) { | |
| 24 static const IPCCall create_params = { | |
| 25 {IPC_NTCREATEFILE_TAG, | |
| 26 {WCHAR_TYPE, | |
| 27 UINT32_TYPE, | |
| 28 UINT32_TYPE, | |
| 29 UINT32_TYPE, | |
| 30 UINT32_TYPE, | |
| 31 UINT32_TYPE, | |
| 32 UINT32_TYPE}}, | |
| 33 reinterpret_cast<CallbackGeneric>(&FilesystemDispatcher::NtCreateFile)}; | |
| 34 | |
| 35 static const IPCCall open_file = { | |
| 36 {IPC_NTOPENFILE_TAG, | |
| 37 {WCHAR_TYPE, UINT32_TYPE, UINT32_TYPE, UINT32_TYPE, UINT32_TYPE}}, | |
| 38 reinterpret_cast<CallbackGeneric>(&FilesystemDispatcher::NtOpenFile)}; | |
| 39 | |
| 40 static const IPCCall attribs = { | |
| 41 {IPC_NTQUERYATTRIBUTESFILE_TAG, {WCHAR_TYPE, UINT32_TYPE, INOUTPTR_TYPE}}, | |
| 42 reinterpret_cast<CallbackGeneric>( | |
| 43 &FilesystemDispatcher::NtQueryAttributesFile)}; | |
| 44 | |
| 45 static const IPCCall full_attribs = { | |
| 46 {IPC_NTQUERYFULLATTRIBUTESFILE_TAG, | |
| 47 {WCHAR_TYPE, UINT32_TYPE, INOUTPTR_TYPE}}, | |
| 48 reinterpret_cast<CallbackGeneric>( | |
| 49 &FilesystemDispatcher::NtQueryFullAttributesFile)}; | |
| 50 | |
| 51 static const IPCCall set_info = { | |
| 52 {IPC_NTSETINFO_RENAME_TAG, | |
| 53 {VOIDPTR_TYPE, INOUTPTR_TYPE, INOUTPTR_TYPE, UINT32_TYPE, UINT32_TYPE}}, | |
| 54 reinterpret_cast<CallbackGeneric>( | |
| 55 &FilesystemDispatcher::NtSetInformationFile)}; | |
| 56 | |
| 57 ipc_calls_.push_back(create_params); | |
| 58 ipc_calls_.push_back(open_file); | |
| 59 ipc_calls_.push_back(attribs); | |
| 60 ipc_calls_.push_back(full_attribs); | |
| 61 ipc_calls_.push_back(set_info); | |
| 62 } | |
| 63 | |
| 64 bool FilesystemDispatcher::SetupService(InterceptionManager* manager, | |
| 65 int service) { | |
| 66 switch (service) { | |
| 67 case IPC_NTCREATEFILE_TAG: | |
| 68 return INTERCEPT_NT(manager, NtCreateFile, CREATE_FILE_ID, 48); | |
| 69 | |
| 70 case IPC_NTOPENFILE_TAG: | |
| 71 return INTERCEPT_NT(manager, NtOpenFile, OPEN_FILE_ID, 28); | |
| 72 | |
| 73 case IPC_NTQUERYATTRIBUTESFILE_TAG: | |
| 74 return INTERCEPT_NT(manager, NtQueryAttributesFile, QUERY_ATTRIB_FILE_ID, | |
| 75 12); | |
| 76 | |
| 77 case IPC_NTQUERYFULLATTRIBUTESFILE_TAG: | |
| 78 return INTERCEPT_NT(manager, NtQueryFullAttributesFile, | |
| 79 QUERY_FULL_ATTRIB_FILE_ID, 12); | |
| 80 | |
| 81 case IPC_NTSETINFO_RENAME_TAG: | |
| 82 return INTERCEPT_NT(manager, NtSetInformationFile, SET_INFO_FILE_ID, 24); | |
| 83 | |
| 84 default: | |
| 85 return false; | |
| 86 } | |
| 87 } | |
| 88 | |
| 89 bool FilesystemDispatcher::NtCreateFile(IPCInfo* ipc, | |
| 90 base::string16* name, | |
| 91 uint32_t attributes, | |
| 92 uint32_t desired_access, | |
| 93 uint32_t file_attributes, | |
| 94 uint32_t share_access, | |
| 95 uint32_t create_disposition, | |
| 96 uint32_t create_options) { | |
| 97 if (!PreProcessName(name)) { | |
| 98 // The path requested might contain a reparse point. | |
| 99 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; | |
| 100 return true; | |
| 101 } | |
| 102 | |
| 103 const wchar_t* filename = name->c_str(); | |
| 104 | |
| 105 uint32_t broker = TRUE; | |
| 106 CountedParameterSet<OpenFile> params; | |
| 107 params[OpenFile::NAME] = ParamPickerMake(filename); | |
| 108 params[OpenFile::ACCESS] = ParamPickerMake(desired_access); | |
| 109 params[OpenFile::DISPOSITION] = ParamPickerMake(create_disposition); | |
| 110 params[OpenFile::OPTIONS] = ParamPickerMake(create_options); | |
| 111 params[OpenFile::BROKER] = ParamPickerMake(broker); | |
| 112 | |
| 113 // To evaluate the policy we need to call back to the policy object. We | |
| 114 // are just middlemen in the operation since is the FileSystemPolicy which | |
| 115 // knows what to do. | |
| 116 EvalResult result = policy_base_->EvalPolicy(IPC_NTCREATEFILE_TAG, | |
| 117 params.GetBase()); | |
| 118 HANDLE handle; | |
| 119 ULONG_PTR io_information = 0; | |
| 120 NTSTATUS nt_status; | |
| 121 if (!FileSystemPolicy::CreateFileAction(result, *ipc->client_info, *name, | |
| 122 attributes, desired_access, | |
| 123 file_attributes, share_access, | |
| 124 create_disposition, create_options, | |
| 125 &handle, &nt_status, | |
| 126 &io_information)) { | |
| 127 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; | |
| 128 return true; | |
| 129 } | |
| 130 // Return operation status on the IPC. | |
| 131 ipc->return_info.extended[0].ulong_ptr = io_information; | |
| 132 ipc->return_info.nt_status = nt_status; | |
| 133 ipc->return_info.handle = handle; | |
| 134 return true; | |
| 135 } | |
| 136 | |
| 137 bool FilesystemDispatcher::NtOpenFile(IPCInfo* ipc, | |
| 138 base::string16* name, | |
| 139 uint32_t attributes, | |
| 140 uint32_t desired_access, | |
| 141 uint32_t share_access, | |
| 142 uint32_t open_options) { | |
| 143 if (!PreProcessName(name)) { | |
| 144 // The path requested might contain a reparse point. | |
| 145 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; | |
| 146 return true; | |
| 147 } | |
| 148 | |
| 149 const wchar_t* filename = name->c_str(); | |
| 150 | |
| 151 uint32_t broker = TRUE; | |
| 152 uint32_t create_disposition = FILE_OPEN; | |
| 153 CountedParameterSet<OpenFile> params; | |
| 154 params[OpenFile::NAME] = ParamPickerMake(filename); | |
| 155 params[OpenFile::ACCESS] = ParamPickerMake(desired_access); | |
| 156 params[OpenFile::DISPOSITION] = ParamPickerMake(create_disposition); | |
| 157 params[OpenFile::OPTIONS] = ParamPickerMake(open_options); | |
| 158 params[OpenFile::BROKER] = ParamPickerMake(broker); | |
| 159 | |
| 160 // To evaluate the policy we need to call back to the policy object. We | |
| 161 // are just middlemen in the operation since is the FileSystemPolicy which | |
| 162 // knows what to do. | |
| 163 EvalResult result = policy_base_->EvalPolicy(IPC_NTOPENFILE_TAG, | |
| 164 params.GetBase()); | |
| 165 HANDLE handle; | |
| 166 ULONG_PTR io_information = 0; | |
| 167 NTSTATUS nt_status; | |
| 168 if (!FileSystemPolicy::OpenFileAction(result, *ipc->client_info, *name, | |
| 169 attributes, desired_access, | |
| 170 share_access, open_options, &handle, | |
| 171 &nt_status, &io_information)) { | |
| 172 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; | |
| 173 return true; | |
| 174 } | |
| 175 // Return operation status on the IPC. | |
| 176 ipc->return_info.extended[0].ulong_ptr = io_information; | |
| 177 ipc->return_info.nt_status = nt_status; | |
| 178 ipc->return_info.handle = handle; | |
| 179 return true; | |
| 180 } | |
| 181 | |
| 182 bool FilesystemDispatcher::NtQueryAttributesFile(IPCInfo* ipc, | |
| 183 base::string16* name, | |
| 184 uint32_t attributes, | |
| 185 CountedBuffer* info) { | |
| 186 if (sizeof(FILE_BASIC_INFORMATION) != info->Size()) | |
| 187 return false; | |
| 188 | |
| 189 if (!PreProcessName(name)) { | |
| 190 // The path requested might contain a reparse point. | |
| 191 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; | |
| 192 return true; | |
| 193 } | |
| 194 | |
| 195 uint32_t broker = TRUE; | |
| 196 const wchar_t* filename = name->c_str(); | |
| 197 CountedParameterSet<FileName> params; | |
| 198 params[FileName::NAME] = ParamPickerMake(filename); | |
| 199 params[FileName::BROKER] = ParamPickerMake(broker); | |
| 200 | |
| 201 // To evaluate the policy we need to call back to the policy object. We | |
| 202 // are just middlemen in the operation since is the FileSystemPolicy which | |
| 203 // knows what to do. | |
| 204 EvalResult result = policy_base_->EvalPolicy(IPC_NTQUERYATTRIBUTESFILE_TAG, | |
| 205 params.GetBase()); | |
| 206 | |
| 207 FILE_BASIC_INFORMATION* information = | |
| 208 reinterpret_cast<FILE_BASIC_INFORMATION*>(info->Buffer()); | |
| 209 NTSTATUS nt_status; | |
| 210 if (!FileSystemPolicy::QueryAttributesFileAction(result, *ipc->client_info, | |
| 211 *name, attributes, | |
| 212 information, &nt_status)) { | |
| 213 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; | |
| 214 return true; | |
| 215 } | |
| 216 | |
| 217 // Return operation status on the IPC. | |
| 218 ipc->return_info.nt_status = nt_status; | |
| 219 return true; | |
| 220 } | |
| 221 | |
| 222 bool FilesystemDispatcher::NtQueryFullAttributesFile(IPCInfo* ipc, | |
| 223 base::string16* name, | |
| 224 uint32_t attributes, | |
| 225 CountedBuffer* info) { | |
| 226 if (sizeof(FILE_NETWORK_OPEN_INFORMATION) != info->Size()) | |
| 227 return false; | |
| 228 | |
| 229 if (!PreProcessName(name)) { | |
| 230 // The path requested might contain a reparse point. | |
| 231 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; | |
| 232 return true; | |
| 233 } | |
| 234 | |
| 235 uint32_t broker = TRUE; | |
| 236 const wchar_t* filename = name->c_str(); | |
| 237 CountedParameterSet<FileName> params; | |
| 238 params[FileName::NAME] = ParamPickerMake(filename); | |
| 239 params[FileName::BROKER] = ParamPickerMake(broker); | |
| 240 | |
| 241 // To evaluate the policy we need to call back to the policy object. We | |
| 242 // are just middlemen in the operation since is the FileSystemPolicy which | |
| 243 // knows what to do. | |
| 244 EvalResult result = policy_base_->EvalPolicy( | |
| 245 IPC_NTQUERYFULLATTRIBUTESFILE_TAG, params.GetBase()); | |
| 246 | |
| 247 FILE_NETWORK_OPEN_INFORMATION* information = | |
| 248 reinterpret_cast<FILE_NETWORK_OPEN_INFORMATION*>(info->Buffer()); | |
| 249 NTSTATUS nt_status; | |
| 250 if (!FileSystemPolicy::QueryFullAttributesFileAction(result, | |
| 251 *ipc->client_info, | |
| 252 *name, attributes, | |
| 253 information, | |
| 254 &nt_status)) { | |
| 255 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; | |
| 256 return true; | |
| 257 } | |
| 258 | |
| 259 // Return operation status on the IPC. | |
| 260 ipc->return_info.nt_status = nt_status; | |
| 261 return true; | |
| 262 } | |
| 263 | |
| 264 bool FilesystemDispatcher::NtSetInformationFile(IPCInfo* ipc, | |
| 265 HANDLE handle, | |
| 266 CountedBuffer* status, | |
| 267 CountedBuffer* info, | |
| 268 uint32_t length, | |
| 269 uint32_t info_class) { | |
| 270 if (sizeof(IO_STATUS_BLOCK) != status->Size()) | |
| 271 return false; | |
| 272 if (length != info->Size()) | |
| 273 return false; | |
| 274 | |
| 275 FILE_RENAME_INFORMATION* rename_info = | |
| 276 reinterpret_cast<FILE_RENAME_INFORMATION*>(info->Buffer()); | |
| 277 | |
| 278 if (!IsSupportedRenameCall(rename_info, length, info_class)) | |
| 279 return false; | |
| 280 | |
| 281 base::string16 name; | |
| 282 name.assign(rename_info->FileName, rename_info->FileNameLength / | |
| 283 sizeof(rename_info->FileName[0])); | |
| 284 if (!PreProcessName(&name)) { | |
| 285 // The path requested might contain a reparse point. | |
| 286 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; | |
| 287 return true; | |
| 288 } | |
| 289 | |
| 290 uint32_t broker = TRUE; | |
| 291 const wchar_t* filename = name.c_str(); | |
| 292 CountedParameterSet<FileName> params; | |
| 293 params[FileName::NAME] = ParamPickerMake(filename); | |
| 294 params[FileName::BROKER] = ParamPickerMake(broker); | |
| 295 | |
| 296 // To evaluate the policy we need to call back to the policy object. We | |
| 297 // are just middlemen in the operation since is the FileSystemPolicy which | |
| 298 // knows what to do. | |
| 299 EvalResult result = policy_base_->EvalPolicy(IPC_NTSETINFO_RENAME_TAG, | |
| 300 params.GetBase()); | |
| 301 | |
| 302 IO_STATUS_BLOCK* io_status = | |
| 303 reinterpret_cast<IO_STATUS_BLOCK*>(status->Buffer()); | |
| 304 NTSTATUS nt_status; | |
| 305 if (!FileSystemPolicy::SetInformationFileAction(result, *ipc->client_info, | |
| 306 handle, rename_info, length, | |
| 307 info_class, io_status, | |
| 308 &nt_status)) { | |
| 309 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; | |
| 310 return true; | |
| 311 } | |
| 312 | |
| 313 // Return operation status on the IPC. | |
| 314 ipc->return_info.nt_status = nt_status; | |
| 315 return true; | |
| 316 } | |
| 317 | |
| 318 } // namespace sandbox | |
| OLD | NEW |