diff options
Diffstat (limited to 'sandbox/src/filesystem_policy.cc')
-rw-r--r-- | sandbox/src/filesystem_policy.cc | 387 |
1 files changed, 0 insertions, 387 deletions
diff --git a/sandbox/src/filesystem_policy.cc b/sandbox/src/filesystem_policy.cc deleted file mode 100644 index 385f4ae..0000000 --- a/sandbox/src/filesystem_policy.cc +++ /dev/null @@ -1,387 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <string> - -#include "sandbox/src/filesystem_policy.h" - -#include "base/logging.h" -#include "base/win/scoped_handle.h" -#include "sandbox/src/ipc_tags.h" -#include "sandbox/src/policy_engine_opcodes.h" -#include "sandbox/src/policy_params.h" -#include "sandbox/src/sandbox_utils.h" -#include "sandbox/src/sandbox_types.h" -#include "sandbox/src/win_utils.h" - -namespace { - -NTSTATUS NtCreateFileInTarget(HANDLE* target_file_handle, - ACCESS_MASK desired_access, - OBJECT_ATTRIBUTES* obj_attributes, - IO_STATUS_BLOCK* io_status_block, - ULONG file_attributes, - ULONG share_access, - ULONG create_disposition, - ULONG create_options, - PVOID ea_buffer, - ULONG ea_lenght, - HANDLE target_process) { - NtCreateFileFunction NtCreateFile = NULL; - ResolveNTFunctionPtr("NtCreateFile", &NtCreateFile); - - HANDLE local_handle = INVALID_HANDLE_VALUE; - NTSTATUS status = NtCreateFile(&local_handle, desired_access, obj_attributes, - io_status_block, NULL, file_attributes, - share_access, create_disposition, - create_options, ea_buffer, ea_lenght); - if (!NT_SUCCESS(status)) { - return status; - } - - if (!sandbox::SameObject(local_handle, obj_attributes->ObjectName->Buffer)) { - // The handle points somewhere else. Fail the operation. - ::CloseHandle(local_handle); - return STATUS_ACCESS_DENIED; - } - - if (!::DuplicateHandle(::GetCurrentProcess(), local_handle, - target_process, target_file_handle, 0, FALSE, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { - ::CloseHandle(local_handle); - return STATUS_ACCESS_DENIED; - } - return STATUS_SUCCESS; -} - -} // namespace. - -namespace sandbox { - -bool FileSystemPolicy::GenerateRules(const wchar_t* name, - TargetPolicy::Semantics semantics, - LowLevelPolicy* policy) { - std::wstring mod_name(name); - if (mod_name.empty()) { - return false; - } - - // Don't do any pre-processing if the name starts like the the native - // object manager style. - if (0 != _wcsnicmp(mod_name.c_str(), kNTObjManPrefix, kNTObjManPrefixLen)) { - // TODO(cpu) bug 32224: This prefix add is a hack because we don't have the - // infrastructure to normalize names. In any case we need to escape the - // question marks. - if (!PreProcessName(mod_name, &mod_name)) { - // The path to be added might contain a reparse point. - NOTREACHED(); - return false; - } - if (0 != mod_name.compare(0, kNTPrefixLen, kNTPrefix)) { - // TODO(nsylvain): Find a better way to do name resolution. Right now we - // take the name and we expand it. - mod_name.insert(0, L"\\/?/?\\"); - name = mod_name.c_str(); - } - } - - EvalResult result = ASK_BROKER; - - // List of supported calls for the filesystem. - const unsigned kCallNtCreateFile = 0x1; - const unsigned kCallNtOpenFile = 0x2; - const unsigned kCallNtQueryAttributesFile = 0x4; - const unsigned kCallNtQueryFullAttributesFile = 0x8; - const unsigned kCallNtSetInfoRename = 0x10; - - DWORD rule_to_add = kCallNtOpenFile | kCallNtCreateFile | - kCallNtQueryAttributesFile | - kCallNtQueryFullAttributesFile | kCallNtSetInfoRename; - - PolicyRule create(result); - PolicyRule open(result); - PolicyRule query(result); - PolicyRule query_full(result); - PolicyRule rename(result); - - switch (semantics) { - case TargetPolicy::FILES_ALLOW_DIR_ANY: { - open.AddNumberMatch(IF, OpenFile::OPTIONS, FILE_DIRECTORY_FILE, AND); - create.AddNumberMatch(IF, OpenFile::OPTIONS, FILE_DIRECTORY_FILE, AND); - break; - } - case TargetPolicy::FILES_ALLOW_READONLY: { - // We consider all flags that are not known to be readonly as potentially - // used for write. - DWORD allowed_flags = FILE_READ_DATA | FILE_READ_ATTRIBUTES | - FILE_READ_EA | SYNCHRONIZE | FILE_EXECUTE | - GENERIC_READ | GENERIC_EXECUTE | READ_CONTROL; - DWORD restricted_flags = ~allowed_flags; - open.AddNumberMatch(IF_NOT, OpenFile::ACCESS, restricted_flags, AND); - create.AddNumberMatch(IF_NOT, OpenFile::ACCESS, restricted_flags, AND); - - // Read only access don't work for rename. - rule_to_add &= ~kCallNtSetInfoRename; - break; - } - case TargetPolicy::FILES_ALLOW_QUERY: { - // Here we don't want to add policy for the open or the create. - rule_to_add &= ~(kCallNtOpenFile | kCallNtCreateFile | - kCallNtSetInfoRename); - break; - } - case TargetPolicy::FILES_ALLOW_ANY: { - break; - } - default: { - NOTREACHED(); - return false; - } - } - - if ((rule_to_add & kCallNtCreateFile) && - (!create.AddStringMatch(IF, OpenFile::NAME, name, CASE_INSENSITIVE) || - !policy->AddRule(IPC_NTCREATEFILE_TAG, &create))) { - return false; - } - - if ((rule_to_add & kCallNtOpenFile) && - (!open.AddStringMatch(IF, OpenFile::NAME, name, CASE_INSENSITIVE) || - !policy->AddRule(IPC_NTOPENFILE_TAG, &open))) { - return false; - } - - if ((rule_to_add & kCallNtQueryAttributesFile) && - (!query.AddStringMatch(IF, FileName::NAME, name, CASE_INSENSITIVE) || - !policy->AddRule(IPC_NTQUERYATTRIBUTESFILE_TAG, &query))) { - return false; - } - - if ((rule_to_add & kCallNtQueryFullAttributesFile) && - (!query_full.AddStringMatch(IF, FileName::NAME, name, CASE_INSENSITIVE) - || !policy->AddRule(IPC_NTQUERYFULLATTRIBUTESFILE_TAG, - &query_full))) { - return false; - } - - if ((rule_to_add & kCallNtSetInfoRename) && - (!rename.AddStringMatch(IF, FileName::NAME, name, CASE_INSENSITIVE) || - !policy->AddRule(IPC_NTSETINFO_RENAME_TAG, &rename))) { - return false; - } - - return true; -} - -// Right now we insert two rules, to be evaluated before any user supplied rule: -// - go to the broker if the path doesn't look like the paths that we push on -// the policy (namely \??\something). -// - go to the broker if it looks like this is a short-name path. -// -// It is possible to add a rule to go to the broker in any case; it would look -// something like: -// rule = new PolicyRule(ASK_BROKER); -// rule->AddNumberMatch(IF_NOT, FileName::BROKER, TRUE, AND); -// policy->AddRule(service, rule); -bool FileSystemPolicy::SetInitialRules(LowLevelPolicy* policy) { - PolicyRule format(ASK_BROKER); - PolicyRule short_name(ASK_BROKER); - - bool rv = format.AddNumberMatch(IF_NOT, FileName::BROKER, TRUE, AND); - rv &= format.AddStringMatch(IF_NOT, FileName::NAME, L"\\/?/?\\*", - CASE_SENSITIVE); - - rv &= short_name.AddNumberMatch(IF_NOT, FileName::BROKER, TRUE, AND); - rv &= short_name.AddStringMatch(IF, FileName::NAME, L"*~*", CASE_SENSITIVE); - - if (!rv || !policy->AddRule(IPC_NTCREATEFILE_TAG, &format)) - return false; - - if (!policy->AddRule(IPC_NTCREATEFILE_TAG, &short_name)) - return false; - - if (!policy->AddRule(IPC_NTOPENFILE_TAG, &format)) - return false; - - if (!policy->AddRule(IPC_NTOPENFILE_TAG, &short_name)) - return false; - - if (!policy->AddRule(IPC_NTQUERYATTRIBUTESFILE_TAG, &format)) - return false; - - if (!policy->AddRule(IPC_NTQUERYATTRIBUTESFILE_TAG, &short_name)) - return false; - - if (!policy->AddRule(IPC_NTQUERYFULLATTRIBUTESFILE_TAG, &format)) - return false; - - if (!policy->AddRule(IPC_NTQUERYFULLATTRIBUTESFILE_TAG, &short_name)) - return false; - - if (!policy->AddRule(IPC_NTSETINFO_RENAME_TAG, &format)) - return false; - - if (!policy->AddRule(IPC_NTSETINFO_RENAME_TAG, &short_name)) - return false; - - return true; -} - -bool FileSystemPolicy::CreateFileAction(EvalResult eval_result, - const ClientInfo& client_info, - const std::wstring &file, - uint32 attributes, - uint32 desired_access, - uint32 file_attributes, - uint32 share_access, - uint32 create_disposition, - uint32 create_options, - HANDLE *handle, - NTSTATUS* nt_status, - ULONG_PTR *io_information) { - // The only action supported is ASK_BROKER which means create the requested - // file as specified. - if (ASK_BROKER != eval_result) { - *nt_status = STATUS_ACCESS_DENIED; - return false; - } - IO_STATUS_BLOCK io_block = {0}; - UNICODE_STRING uni_name = {0}; - OBJECT_ATTRIBUTES obj_attributes = {0}; - InitObjectAttribs(file, attributes, NULL, &obj_attributes, &uni_name); - *nt_status = NtCreateFileInTarget(handle, desired_access, &obj_attributes, - &io_block, file_attributes, share_access, - create_disposition, create_options, NULL, - 0, client_info.process); - - *io_information = io_block.Information; - return true; -} - -bool FileSystemPolicy::OpenFileAction(EvalResult eval_result, - const ClientInfo& client_info, - const std::wstring &file, - uint32 attributes, - uint32 desired_access, - uint32 share_access, - uint32 open_options, - HANDLE *handle, - NTSTATUS* nt_status, - ULONG_PTR *io_information) { - // The only action supported is ASK_BROKER which means open the requested - // file as specified. - if (ASK_BROKER != eval_result) { - *nt_status = STATUS_ACCESS_DENIED; - return true; - } - // An NtOpen is equivalent to an NtCreate with FileAttributes = 0 and - // CreateDisposition = FILE_OPEN. - IO_STATUS_BLOCK io_block = {0}; - UNICODE_STRING uni_name = {0}; - OBJECT_ATTRIBUTES obj_attributes = {0}; - InitObjectAttribs(file, attributes, NULL, &obj_attributes, &uni_name); - *nt_status = NtCreateFileInTarget(handle, desired_access, &obj_attributes, - &io_block, 0, share_access, FILE_OPEN, - open_options, NULL, 0, - client_info.process); - - *io_information = io_block.Information; - return true; -} - -bool FileSystemPolicy::QueryAttributesFileAction( - EvalResult eval_result, - const ClientInfo& client_info, - const std::wstring &file, - uint32 attributes, - FILE_BASIC_INFORMATION* file_info, - NTSTATUS* nt_status) { - // The only action supported is ASK_BROKER which means query the requested - // file as specified. - if (ASK_BROKER != eval_result) { - *nt_status = STATUS_ACCESS_DENIED; - return true; - } - - NtQueryAttributesFileFunction NtQueryAttributesFile = NULL; - ResolveNTFunctionPtr("NtQueryAttributesFile", &NtQueryAttributesFile); - - UNICODE_STRING uni_name = {0}; - OBJECT_ATTRIBUTES obj_attributes = {0}; - InitObjectAttribs(file, attributes, NULL, &obj_attributes, &uni_name); - *nt_status = NtQueryAttributesFile(&obj_attributes, file_info); - - return true; -} - -bool FileSystemPolicy::QueryFullAttributesFileAction( - EvalResult eval_result, - const ClientInfo& client_info, - const std::wstring &file, - uint32 attributes, - FILE_NETWORK_OPEN_INFORMATION* file_info, - NTSTATUS* nt_status) { - // The only action supported is ASK_BROKER which means query the requested - // file as specified. - if (ASK_BROKER != eval_result) { - *nt_status = STATUS_ACCESS_DENIED; - return true; - } - - NtQueryFullAttributesFileFunction NtQueryFullAttributesFile = NULL; - ResolveNTFunctionPtr("NtQueryFullAttributesFile", &NtQueryFullAttributesFile); - - UNICODE_STRING uni_name = {0}; - OBJECT_ATTRIBUTES obj_attributes = {0}; - InitObjectAttribs(file, attributes, NULL, &obj_attributes, &uni_name); - *nt_status = NtQueryFullAttributesFile(&obj_attributes, file_info); - - return true; -} - -bool FileSystemPolicy::SetInformationFileAction( - EvalResult eval_result, const ClientInfo& client_info, - HANDLE target_file_handle, void* file_info, uint32 length, - uint32 info_class, IO_STATUS_BLOCK* io_block, - NTSTATUS* nt_status) { - // The only action supported is ASK_BROKER which means open the requested - // file as specified. - if (ASK_BROKER != eval_result) { - *nt_status = STATUS_ACCESS_DENIED; - return true; - } - - NtSetInformationFileFunction NtSetInformationFile = NULL; - ResolveNTFunctionPtr("NtSetInformationFile", &NtSetInformationFile); - - HANDLE local_handle = NULL; - if (!::DuplicateHandle(client_info.process, target_file_handle, - ::GetCurrentProcess(), &local_handle, 0, FALSE, - DUPLICATE_SAME_ACCESS)) { - *nt_status = STATUS_ACCESS_DENIED; - return true; - } - - base::win::ScopedHandle handle(local_handle); - - FILE_INFORMATION_CLASS file_info_class = - static_cast<FILE_INFORMATION_CLASS>(info_class); - *nt_status = NtSetInformationFile(local_handle, io_block, file_info, length, - file_info_class); - - return true; -} - -bool PreProcessName(const std::wstring& path, std::wstring* new_path) { - ConvertToLongPath(path, new_path); - - bool reparsed = false; - if (ERROR_SUCCESS != IsReparsePoint(*new_path, &reparsed)) - return false; - - // We can't process reparsed file. - return !reparsed; -} - -} // namespace sandbox |