1// Copyright (c) 2012 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/handle_policy.h" 6 7#include <string> 8 9#include "base/win/scoped_handle.h" 10#include "sandbox/win/src/broker_services.h" 11#include "sandbox/win/src/ipc_tags.h" 12#include "sandbox/win/src/policy_engine_opcodes.h" 13#include "sandbox/win/src/policy_params.h" 14#include "sandbox/win/src/sandbox_types.h" 15#include "sandbox/win/src/sandbox_utils.h" 16 17namespace sandbox { 18 19bool HandlePolicy::GenerateRules(const wchar_t* type_name, 20 TargetPolicy::Semantics semantics, 21 LowLevelPolicy* policy) { 22 PolicyRule duplicate_rule(ASK_BROKER); 23 24 switch (semantics) { 25 case TargetPolicy::HANDLES_DUP_ANY: { 26 if (!duplicate_rule.AddNumberMatch(IF_NOT, HandleTarget::TARGET, 27 ::GetCurrentProcessId(), EQUAL)) { 28 return false; 29 } 30 break; 31 } 32 33 case TargetPolicy::HANDLES_DUP_BROKER: { 34 if (!duplicate_rule.AddNumberMatch(IF, HandleTarget::TARGET, 35 ::GetCurrentProcessId(), EQUAL)) { 36 return false; 37 } 38 break; 39 } 40 41 default: 42 return false; 43 } 44 if (!duplicate_rule.AddStringMatch(IF, HandleTarget::NAME, type_name, 45 CASE_INSENSITIVE)) { 46 return false; 47 } 48 if (!policy->AddRule(IPC_DUPLICATEHANDLEPROXY_TAG, &duplicate_rule)) { 49 return false; 50 } 51 return true; 52} 53 54DWORD HandlePolicy::DuplicateHandleProxyAction(EvalResult eval_result, 55 const ClientInfo& client_info, 56 HANDLE source_handle, 57 DWORD target_process_id, 58 HANDLE* target_handle, 59 DWORD desired_access, 60 DWORD options) { 61 // The only action supported is ASK_BROKER which means duplicate the handle. 62 if (ASK_BROKER != eval_result) { 63 return ERROR_ACCESS_DENIED; 64 } 65 66 base::win::ScopedHandle remote_target_process; 67 if (target_process_id != ::GetCurrentProcessId()) { 68 // Sandboxed children are dynamic, so we check that manually. 69 if (!BrokerServicesBase::GetInstance()->IsActiveTarget(target_process_id)) { 70 return ERROR_ACCESS_DENIED; 71 } 72 73 remote_target_process.Set(::OpenProcess(PROCESS_DUP_HANDLE, FALSE, 74 target_process_id)); 75 if (!remote_target_process.IsValid()) 76 return ::GetLastError(); 77 } 78 79 // If the policy didn't block us and we have no valid target, then the broker 80 // (this process) is the valid target. 81 HANDLE target_process = remote_target_process.IsValid() ? 82 remote_target_process : ::GetCurrentProcess(); 83 DWORD result = ERROR_SUCCESS; 84 if (!::DuplicateHandle(client_info.process, source_handle, target_process, 85 target_handle, desired_access, FALSE, 86 options)) { 87 return ::GetLastError(); 88 } 89 90 return ERROR_SUCCESS; 91} 92 93} // namespace sandbox 94 95