Home | History | Annotate | Download | only in src
      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 
     17 namespace sandbox {
     18 
     19 bool 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 
     54 DWORD HandlePolicy::DuplicateHandleProxyAction(EvalResult eval_result,
     55                                                HANDLE source_handle,
     56                                                DWORD target_process_id,
     57                                                HANDLE* target_handle,
     58                                                DWORD desired_access,
     59                                                DWORD options) {
     60   // The only action supported is ASK_BROKER which means duplicate the handle.
     61   if (ASK_BROKER != eval_result) {
     62     return ERROR_ACCESS_DENIED;
     63   }
     64 
     65   base::win::ScopedHandle remote_target_process;
     66   if (target_process_id != ::GetCurrentProcessId()) {
     67     // Sandboxed children are dynamic, so we check that manually.
     68     if (!BrokerServicesBase::GetInstance()->IsActiveTarget(target_process_id)) {
     69       return ERROR_ACCESS_DENIED;
     70     }
     71 
     72     remote_target_process.Set(::OpenProcess(PROCESS_DUP_HANDLE, FALSE,
     73                                             target_process_id));
     74     if (!remote_target_process.IsValid())
     75       return ::GetLastError();
     76   }
     77 
     78   // If the policy didn't block us and we have no valid target, then the broker
     79   // (this process) is the valid target.
     80   HANDLE target_process = remote_target_process.IsValid() ?
     81                           remote_target_process.Get() : ::GetCurrentProcess();
     82   DWORD result = ERROR_SUCCESS;
     83   if (!::DuplicateHandle(::GetCurrentProcess(), source_handle, target_process,
     84                          target_handle, desired_access, FALSE,
     85                          options)) {
     86     return ::GetLastError();
     87   }
     88 
     89   return ERROR_SUCCESS;
     90 }
     91 
     92 }  // namespace sandbox
     93 
     94