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.
5 #include "sandbox/win/src/handle_policy.h"
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"
19 bool HandlePolicy::GenerateRules(const wchar_t* type_name
,
20 TargetPolicy::Semantics semantics
,
21 LowLevelPolicy
* policy
) {
22 PolicyRule
duplicate_rule(ASK_BROKER
);
25 case TargetPolicy::HANDLES_DUP_ANY
: {
26 if (!duplicate_rule
.AddNumberMatch(IF_NOT
, HandleTarget::TARGET
,
27 ::GetCurrentProcessId(), EQUAL
)) {
33 case TargetPolicy::HANDLES_DUP_BROKER
: {
34 if (!duplicate_rule
.AddNumberMatch(IF
, HandleTarget::TARGET
,
35 ::GetCurrentProcessId(), EQUAL
)) {
44 if (!duplicate_rule
.AddStringMatch(IF
, HandleTarget::NAME
, type_name
,
48 if (!policy
->AddRule(IPC_DUPLICATEHANDLEPROXY_TAG
, &duplicate_rule
)) {
54 DWORD
HandlePolicy::DuplicateHandleProxyAction(EvalResult eval_result
,
55 const ClientInfo
& client_info
,
57 DWORD target_process_id
,
58 HANDLE
* target_handle
,
61 // The only action supported is ASK_BROKER which means duplicate the handle.
62 if (ASK_BROKER
!= eval_result
) {
63 return ERROR_ACCESS_DENIED
;
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
;
73 remote_target_process
.Set(::OpenProcess(PROCESS_DUP_HANDLE
, FALSE
,
75 if (!remote_target_process
.IsValid())
76 return ::GetLastError();
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
.Get() : ::GetCurrentProcess();
83 DWORD result
= ERROR_SUCCESS
;
84 if (!::DuplicateHandle(client_info
.process
, source_handle
, target_process
,
85 target_handle
, desired_access
, FALSE
,
87 return ::GetLastError();
93 } // namespace sandbox