1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/sandbox/win/src/filesystem_dispatcher.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,297 @@ 1.4 +// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#include "sandbox/win/src/filesystem_dispatcher.h" 1.9 + 1.10 +#include "sandbox/win/src/crosscall_client.h" 1.11 +#include "sandbox/win/src/filesystem_interception.h" 1.12 +#include "sandbox/win/src/filesystem_policy.h" 1.13 +#include "sandbox/win/src/interception.h" 1.14 +#include "sandbox/win/src/interceptors.h" 1.15 +#include "sandbox/win/src/ipc_tags.h" 1.16 +#include "sandbox/win/src/policy_broker.h" 1.17 +#include "sandbox/win/src/policy_params.h" 1.18 +#include "sandbox/win/src/sandbox.h" 1.19 +#include "sandbox/win/src/sandbox_nt_util.h" 1.20 + 1.21 +namespace sandbox { 1.22 + 1.23 +FilesystemDispatcher::FilesystemDispatcher(PolicyBase* policy_base) 1.24 + : policy_base_(policy_base) { 1.25 + static const IPCCall create_params = { 1.26 + {IPC_NTCREATEFILE_TAG, WCHAR_TYPE, ULONG_TYPE, ULONG_TYPE, ULONG_TYPE, 1.27 + ULONG_TYPE, ULONG_TYPE, ULONG_TYPE}, 1.28 + reinterpret_cast<CallbackGeneric>(&FilesystemDispatcher::NtCreateFile) 1.29 + }; 1.30 + 1.31 + static const IPCCall open_file = { 1.32 + {IPC_NTOPENFILE_TAG, WCHAR_TYPE, ULONG_TYPE, ULONG_TYPE, ULONG_TYPE, 1.33 + ULONG_TYPE}, 1.34 + reinterpret_cast<CallbackGeneric>(&FilesystemDispatcher::NtOpenFile) 1.35 + }; 1.36 + 1.37 + static const IPCCall attribs = { 1.38 + {IPC_NTQUERYATTRIBUTESFILE_TAG, WCHAR_TYPE, ULONG_TYPE, INOUTPTR_TYPE}, 1.39 + reinterpret_cast<CallbackGeneric>( 1.40 + &FilesystemDispatcher::NtQueryAttributesFile) 1.41 + }; 1.42 + 1.43 + static const IPCCall full_attribs = { 1.44 + {IPC_NTQUERYFULLATTRIBUTESFILE_TAG, WCHAR_TYPE, ULONG_TYPE, INOUTPTR_TYPE}, 1.45 + reinterpret_cast<CallbackGeneric>( 1.46 + &FilesystemDispatcher::NtQueryFullAttributesFile) 1.47 + }; 1.48 + 1.49 + static const IPCCall set_info = { 1.50 + {IPC_NTSETINFO_RENAME_TAG, VOIDPTR_TYPE, INOUTPTR_TYPE, INOUTPTR_TYPE, 1.51 + ULONG_TYPE, ULONG_TYPE}, 1.52 + reinterpret_cast<CallbackGeneric>( 1.53 + &FilesystemDispatcher::NtSetInformationFile) 1.54 + }; 1.55 + 1.56 + ipc_calls_.push_back(create_params); 1.57 + ipc_calls_.push_back(open_file); 1.58 + ipc_calls_.push_back(attribs); 1.59 + ipc_calls_.push_back(full_attribs); 1.60 + ipc_calls_.push_back(set_info); 1.61 +} 1.62 + 1.63 +bool FilesystemDispatcher::SetupService(InterceptionManager* manager, 1.64 + int service) { 1.65 + switch (service) { 1.66 + case IPC_NTCREATEFILE_TAG: 1.67 + return INTERCEPT_NT(manager, NtCreateFile, CREATE_FILE_ID, 48); 1.68 + 1.69 + case IPC_NTOPENFILE_TAG: 1.70 + return INTERCEPT_NT(manager, NtOpenFile, OPEN_FILE_ID, 28); 1.71 + 1.72 + case IPC_NTQUERYATTRIBUTESFILE_TAG: 1.73 + return INTERCEPT_NT(manager, NtQueryAttributesFile, QUERY_ATTRIB_FILE_ID, 1.74 + 12); 1.75 + 1.76 + case IPC_NTQUERYFULLATTRIBUTESFILE_TAG: 1.77 + return INTERCEPT_NT(manager, NtQueryFullAttributesFile, 1.78 + QUERY_FULL_ATTRIB_FILE_ID, 12); 1.79 + 1.80 + case IPC_NTSETINFO_RENAME_TAG: 1.81 + return INTERCEPT_NT(manager, NtSetInformationFile, SET_INFO_FILE_ID, 24); 1.82 + 1.83 + default: 1.84 + return false; 1.85 + } 1.86 +} 1.87 + 1.88 +bool FilesystemDispatcher::NtCreateFile( 1.89 + IPCInfo* ipc, std::wstring* name, DWORD attributes, DWORD desired_access, 1.90 + DWORD file_attributes, DWORD share_access, DWORD create_disposition, 1.91 + DWORD create_options) { 1.92 + if (!PreProcessName(*name, name)) { 1.93 + // The path requested might contain a reparse point. 1.94 + ipc->return_info.nt_status = STATUS_ACCESS_DENIED; 1.95 + return true; 1.96 + } 1.97 + 1.98 + const wchar_t* filename = name->c_str(); 1.99 + 1.100 + ULONG broker = TRUE; 1.101 + CountedParameterSet<OpenFile> params; 1.102 + params[OpenFile::NAME] = ParamPickerMake(filename); 1.103 + params[OpenFile::ACCESS] = ParamPickerMake(desired_access); 1.104 + params[OpenFile::OPTIONS] = ParamPickerMake(create_options); 1.105 + params[OpenFile::BROKER] = ParamPickerMake(broker); 1.106 + 1.107 + // To evaluate the policy we need to call back to the policy object. We 1.108 + // are just middlemen in the operation since is the FileSystemPolicy which 1.109 + // knows what to do. 1.110 + EvalResult result = policy_base_->EvalPolicy(IPC_NTCREATEFILE_TAG, 1.111 + params.GetBase()); 1.112 + HANDLE handle; 1.113 + ULONG_PTR io_information = 0; 1.114 + NTSTATUS nt_status; 1.115 + if (!FileSystemPolicy::CreateFileAction(result, *ipc->client_info, *name, 1.116 + attributes, desired_access, 1.117 + file_attributes, share_access, 1.118 + create_disposition, create_options, 1.119 + &handle, &nt_status, 1.120 + &io_information)) { 1.121 + ipc->return_info.nt_status = STATUS_ACCESS_DENIED; 1.122 + return true; 1.123 + } 1.124 + // Return operation status on the IPC. 1.125 + ipc->return_info.extended[0].ulong_ptr = io_information; 1.126 + ipc->return_info.nt_status = nt_status; 1.127 + ipc->return_info.handle = handle; 1.128 + return true; 1.129 +} 1.130 + 1.131 +bool FilesystemDispatcher::NtOpenFile( 1.132 + IPCInfo* ipc, std::wstring* name, DWORD attributes, DWORD desired_access, 1.133 + DWORD share_access, DWORD open_options) { 1.134 + if (!PreProcessName(*name, name)) { 1.135 + // The path requested might contain a reparse point. 1.136 + ipc->return_info.nt_status = STATUS_ACCESS_DENIED; 1.137 + return true; 1.138 + } 1.139 + 1.140 + const wchar_t* filename = name->c_str(); 1.141 + 1.142 + ULONG broker = TRUE; 1.143 + CountedParameterSet<OpenFile> params; 1.144 + params[OpenFile::NAME] = ParamPickerMake(filename); 1.145 + params[OpenFile::ACCESS] = ParamPickerMake(desired_access); 1.146 + params[OpenFile::OPTIONS] = ParamPickerMake(open_options); 1.147 + params[OpenFile::BROKER] = ParamPickerMake(broker); 1.148 + 1.149 + // To evaluate the policy we need to call back to the policy object. We 1.150 + // are just middlemen in the operation since is the FileSystemPolicy which 1.151 + // knows what to do. 1.152 + EvalResult result = policy_base_->EvalPolicy(IPC_NTOPENFILE_TAG, 1.153 + params.GetBase()); 1.154 + HANDLE handle; 1.155 + ULONG_PTR io_information = 0; 1.156 + NTSTATUS nt_status; 1.157 + if (!FileSystemPolicy::OpenFileAction(result, *ipc->client_info, *name, 1.158 + attributes, desired_access, 1.159 + share_access, open_options, &handle, 1.160 + &nt_status, &io_information)) { 1.161 + ipc->return_info.nt_status = STATUS_ACCESS_DENIED; 1.162 + return true; 1.163 + } 1.164 + // Return operation status on the IPC. 1.165 + ipc->return_info.extended[0].ulong_ptr = io_information; 1.166 + ipc->return_info.nt_status = nt_status; 1.167 + ipc->return_info.handle = handle; 1.168 + return true; 1.169 +} 1.170 + 1.171 +bool FilesystemDispatcher::NtQueryAttributesFile( 1.172 + IPCInfo* ipc, std::wstring* name, DWORD attributes, CountedBuffer* info) { 1.173 + if (sizeof(FILE_BASIC_INFORMATION) != info->Size()) 1.174 + return false; 1.175 + 1.176 + if (!PreProcessName(*name, name)) { 1.177 + // The path requested might contain a reparse point. 1.178 + ipc->return_info.nt_status = STATUS_ACCESS_DENIED; 1.179 + return true; 1.180 + } 1.181 + 1.182 + ULONG broker = TRUE; 1.183 + const wchar_t* filename = name->c_str(); 1.184 + CountedParameterSet<FileName> params; 1.185 + params[FileName::NAME] = ParamPickerMake(filename); 1.186 + params[FileName::BROKER] = ParamPickerMake(broker); 1.187 + 1.188 + // To evaluate the policy we need to call back to the policy object. We 1.189 + // are just middlemen in the operation since is the FileSystemPolicy which 1.190 + // knows what to do. 1.191 + EvalResult result = policy_base_->EvalPolicy(IPC_NTQUERYATTRIBUTESFILE_TAG, 1.192 + params.GetBase()); 1.193 + 1.194 + FILE_BASIC_INFORMATION* information = 1.195 + reinterpret_cast<FILE_BASIC_INFORMATION*>(info->Buffer()); 1.196 + NTSTATUS nt_status; 1.197 + if (!FileSystemPolicy::QueryAttributesFileAction(result, *ipc->client_info, 1.198 + *name, attributes, 1.199 + information, &nt_status)) { 1.200 + ipc->return_info.nt_status = STATUS_ACCESS_DENIED; 1.201 + return true; 1.202 + } 1.203 + 1.204 + // Return operation status on the IPC. 1.205 + ipc->return_info.nt_status = nt_status; 1.206 + return true; 1.207 +} 1.208 + 1.209 +bool FilesystemDispatcher::NtQueryFullAttributesFile( 1.210 + IPCInfo* ipc, std::wstring* name, DWORD attributes, CountedBuffer* info) { 1.211 + if (sizeof(FILE_NETWORK_OPEN_INFORMATION) != info->Size()) 1.212 + return false; 1.213 + 1.214 + if (!PreProcessName(*name, name)) { 1.215 + // The path requested might contain a reparse point. 1.216 + ipc->return_info.nt_status = STATUS_ACCESS_DENIED; 1.217 + return true; 1.218 + } 1.219 + 1.220 + ULONG broker = TRUE; 1.221 + const wchar_t* filename = name->c_str(); 1.222 + CountedParameterSet<FileName> params; 1.223 + params[FileName::NAME] = ParamPickerMake(filename); 1.224 + params[FileName::BROKER] = ParamPickerMake(broker); 1.225 + 1.226 + // To evaluate the policy we need to call back to the policy object. We 1.227 + // are just middlemen in the operation since is the FileSystemPolicy which 1.228 + // knows what to do. 1.229 + EvalResult result = policy_base_->EvalPolicy( 1.230 + IPC_NTQUERYFULLATTRIBUTESFILE_TAG, params.GetBase()); 1.231 + 1.232 + FILE_NETWORK_OPEN_INFORMATION* information = 1.233 + reinterpret_cast<FILE_NETWORK_OPEN_INFORMATION*>(info->Buffer()); 1.234 + NTSTATUS nt_status; 1.235 + if (!FileSystemPolicy::QueryFullAttributesFileAction(result, 1.236 + *ipc->client_info, 1.237 + *name, attributes, 1.238 + information, 1.239 + &nt_status)) { 1.240 + ipc->return_info.nt_status = STATUS_ACCESS_DENIED; 1.241 + return true; 1.242 + } 1.243 + 1.244 + // Return operation status on the IPC. 1.245 + ipc->return_info.nt_status = nt_status; 1.246 + return true; 1.247 +} 1.248 + 1.249 +bool FilesystemDispatcher::NtSetInformationFile( 1.250 + IPCInfo* ipc, HANDLE handle, CountedBuffer* status, CountedBuffer* info, 1.251 + DWORD length, DWORD info_class) { 1.252 + if (sizeof(IO_STATUS_BLOCK) != status->Size()) 1.253 + return false; 1.254 + if (length != info->Size()) 1.255 + return false; 1.256 + 1.257 + FILE_RENAME_INFORMATION* rename_info = 1.258 + reinterpret_cast<FILE_RENAME_INFORMATION*>(info->Buffer()); 1.259 + 1.260 + if (!IsSupportedRenameCall(rename_info, length, info_class)) 1.261 + return false; 1.262 + 1.263 + std::wstring name; 1.264 + name.assign(rename_info->FileName, rename_info->FileNameLength / 1.265 + sizeof(rename_info->FileName[0])); 1.266 + if (!PreProcessName(name, &name)) { 1.267 + // The path requested might contain a reparse point. 1.268 + ipc->return_info.nt_status = STATUS_ACCESS_DENIED; 1.269 + return true; 1.270 + } 1.271 + 1.272 + ULONG broker = TRUE; 1.273 + const wchar_t* filename = name.c_str(); 1.274 + CountedParameterSet<FileName> params; 1.275 + params[FileName::NAME] = ParamPickerMake(filename); 1.276 + params[FileName::BROKER] = ParamPickerMake(broker); 1.277 + 1.278 + // To evaluate the policy we need to call back to the policy object. We 1.279 + // are just middlemen in the operation since is the FileSystemPolicy which 1.280 + // knows what to do. 1.281 + EvalResult result = policy_base_->EvalPolicy(IPC_NTSETINFO_RENAME_TAG, 1.282 + params.GetBase()); 1.283 + 1.284 + IO_STATUS_BLOCK* io_status = 1.285 + reinterpret_cast<IO_STATUS_BLOCK*>(status->Buffer()); 1.286 + NTSTATUS nt_status; 1.287 + if (!FileSystemPolicy::SetInformationFileAction(result, *ipc->client_info, 1.288 + handle, rename_info, length, 1.289 + info_class, io_status, 1.290 + &nt_status)) { 1.291 + ipc->return_info.nt_status = STATUS_ACCESS_DENIED; 1.292 + return true; 1.293 + } 1.294 + 1.295 + // Return operation status on the IPC. 1.296 + ipc->return_info.nt_status = nt_status; 1.297 + return true; 1.298 +} 1.299 + 1.300 +} // namespace sandbox