security/sandbox/win/src/process_thread_policy.cc

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/sandbox/win/src/process_thread_policy.cc	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,242 @@
     1.4 +// Copyright (c) 2011 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/process_thread_policy.h"
     1.9 +
    1.10 +#include <string>
    1.11 +
    1.12 +#include "base/memory/scoped_ptr.h"
    1.13 +#include "sandbox/win/src/ipc_tags.h"
    1.14 +#include "sandbox/win/src/nt_internals.h"
    1.15 +#include "sandbox/win/src/policy_engine_opcodes.h"
    1.16 +#include "sandbox/win/src/policy_params.h"
    1.17 +#include "sandbox/win/src/sandbox_types.h"
    1.18 +#include "sandbox/win/src/win_utils.h"
    1.19 +
    1.20 +namespace {
    1.21 +
    1.22 +// These are the only safe rights that can be given to a sandboxed
    1.23 +// process for the process created by the broker. All others are potential
    1.24 +// vectors of privilege elevation.
    1.25 +const DWORD kProcessRights = SYNCHRONIZE |
    1.26 +                             PROCESS_QUERY_INFORMATION |
    1.27 +                             PROCESS_QUERY_LIMITED_INFORMATION |
    1.28 +                             PROCESS_TERMINATE |
    1.29 +                             PROCESS_SUSPEND_RESUME;
    1.30 +
    1.31 +const DWORD kThreadRights = SYNCHRONIZE |
    1.32 +                            THREAD_TERMINATE |
    1.33 +                            THREAD_SUSPEND_RESUME |
    1.34 +                            THREAD_QUERY_INFORMATION |
    1.35 +                            THREAD_QUERY_LIMITED_INFORMATION |
    1.36 +                            THREAD_SET_LIMITED_INFORMATION;
    1.37 +
    1.38 +// Creates a child process and duplicates the handles to 'target_process'. The
    1.39 +// remaining parameters are the same as CreateProcess().
    1.40 +BOOL CreateProcessExWHelper(HANDLE target_process, BOOL give_full_access,
    1.41 +                            LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
    1.42 +                            LPSECURITY_ATTRIBUTES lpProcessAttributes,
    1.43 +                            LPSECURITY_ATTRIBUTES lpThreadAttributes,
    1.44 +                            BOOL bInheritHandles, DWORD dwCreationFlags,
    1.45 +                            LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory,
    1.46 +                            LPSTARTUPINFOW lpStartupInfo,
    1.47 +                            LPPROCESS_INFORMATION lpProcessInformation) {
    1.48 +  if (!::CreateProcessW(lpApplicationName, lpCommandLine, lpProcessAttributes,
    1.49 +                        lpThreadAttributes, bInheritHandles, dwCreationFlags,
    1.50 +                        lpEnvironment, lpCurrentDirectory, lpStartupInfo,
    1.51 +                        lpProcessInformation)) {
    1.52 +    return FALSE;
    1.53 +  }
    1.54 +
    1.55 +  DWORD process_access = kProcessRights;
    1.56 +  DWORD thread_access = kThreadRights;
    1.57 +  if (give_full_access) {
    1.58 +    process_access = PROCESS_ALL_ACCESS;
    1.59 +    thread_access = THREAD_ALL_ACCESS;
    1.60 +  }
    1.61 +  if (!::DuplicateHandle(::GetCurrentProcess(), lpProcessInformation->hProcess,
    1.62 +                         target_process, &lpProcessInformation->hProcess,
    1.63 +                         process_access, FALSE, DUPLICATE_CLOSE_SOURCE)) {
    1.64 +    ::CloseHandle(lpProcessInformation->hThread);
    1.65 +    return FALSE;
    1.66 +  }
    1.67 +  if (!::DuplicateHandle(::GetCurrentProcess(), lpProcessInformation->hThread,
    1.68 +                         target_process, &lpProcessInformation->hThread,
    1.69 +                         thread_access, FALSE, DUPLICATE_CLOSE_SOURCE)) {
    1.70 +    return FALSE;
    1.71 +  }
    1.72 +  return TRUE;
    1.73 +}
    1.74 +
    1.75 +}
    1.76 +
    1.77 +namespace sandbox {
    1.78 +
    1.79 +bool ProcessPolicy::GenerateRules(const wchar_t* name,
    1.80 +                                  TargetPolicy::Semantics semantics,
    1.81 +                                  LowLevelPolicy* policy) {
    1.82 +  scoped_ptr<PolicyRule> process;
    1.83 +  switch (semantics) {
    1.84 +    case TargetPolicy::PROCESS_MIN_EXEC: {
    1.85 +      process.reset(new PolicyRule(GIVE_READONLY));
    1.86 +      break;
    1.87 +    };
    1.88 +    case TargetPolicy::PROCESS_ALL_EXEC: {
    1.89 +      process.reset(new PolicyRule(GIVE_ALLACCESS));
    1.90 +      break;
    1.91 +    };
    1.92 +    default: {
    1.93 +      return false;
    1.94 +    };
    1.95 +  }
    1.96 +
    1.97 +  if (!process->AddStringMatch(IF, NameBased::NAME, name, CASE_INSENSITIVE)) {
    1.98 +    return false;
    1.99 +  }
   1.100 +  if (!policy->AddRule(IPC_CREATEPROCESSW_TAG, process.get())) {
   1.101 +    return false;
   1.102 +  }
   1.103 +  return true;
   1.104 +}
   1.105 +
   1.106 +NTSTATUS ProcessPolicy::OpenThreadAction(const ClientInfo& client_info,
   1.107 +                                         uint32 desired_access,
   1.108 +                                         uint32 thread_id,
   1.109 +                                         HANDLE* handle) {
   1.110 +  *handle = NULL;
   1.111 +
   1.112 +  NtOpenThreadFunction NtOpenThread = NULL;
   1.113 +  ResolveNTFunctionPtr("NtOpenThread", &NtOpenThread);
   1.114 +
   1.115 +  OBJECT_ATTRIBUTES attributes = {0};
   1.116 +  attributes.Length = sizeof(attributes);
   1.117 +  CLIENT_ID client_id = {0};
   1.118 +  client_id.UniqueProcess = reinterpret_cast<PVOID>(
   1.119 +                                static_cast<ULONG_PTR>(client_info.process_id));
   1.120 +  client_id.UniqueThread =
   1.121 +      reinterpret_cast<PVOID>(static_cast<ULONG_PTR>(thread_id));
   1.122 +
   1.123 +  HANDLE local_handle;
   1.124 +  NTSTATUS status = NtOpenThread(&local_handle, desired_access, &attributes,
   1.125 +                                 &client_id);
   1.126 +  if (NT_SUCCESS(status)) {
   1.127 +    if (!::DuplicateHandle(::GetCurrentProcess(), local_handle,
   1.128 +                           client_info.process, handle, 0, FALSE,
   1.129 +                           DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
   1.130 +      ::CloseHandle(local_handle);
   1.131 +      return STATUS_ACCESS_DENIED;
   1.132 +    }
   1.133 +  }
   1.134 +
   1.135 +  return status;
   1.136 +}
   1.137 +
   1.138 +NTSTATUS ProcessPolicy::OpenProcessAction(const ClientInfo& client_info,
   1.139 +                                          uint32 desired_access,
   1.140 +                                          uint32 process_id,
   1.141 +                                          HANDLE* handle) {
   1.142 +  *handle = NULL;
   1.143 +
   1.144 +  NtOpenProcessFunction NtOpenProcess = NULL;
   1.145 +  ResolveNTFunctionPtr("NtOpenProcess", &NtOpenProcess);
   1.146 +
   1.147 +  if (client_info.process_id != process_id)
   1.148 +    return STATUS_ACCESS_DENIED;
   1.149 +
   1.150 +  OBJECT_ATTRIBUTES attributes = {0};
   1.151 +  attributes.Length = sizeof(attributes);
   1.152 +  CLIENT_ID client_id = {0};
   1.153 +  client_id.UniqueProcess = reinterpret_cast<PVOID>(
   1.154 +                                static_cast<ULONG_PTR>(client_info.process_id));
   1.155 +  HANDLE local_handle;
   1.156 +  NTSTATUS status = NtOpenProcess(&local_handle, desired_access, &attributes,
   1.157 +                                  &client_id);
   1.158 +  if (NT_SUCCESS(status)) {
   1.159 +    if (!::DuplicateHandle(::GetCurrentProcess(), local_handle,
   1.160 +                           client_info.process, handle, 0, FALSE,
   1.161 +                           DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
   1.162 +      ::CloseHandle(local_handle);
   1.163 +      return STATUS_ACCESS_DENIED;
   1.164 +    }
   1.165 +  }
   1.166 +
   1.167 +  return status;
   1.168 +}
   1.169 +
   1.170 +NTSTATUS ProcessPolicy::OpenProcessTokenAction(const ClientInfo& client_info,
   1.171 +                                               HANDLE process,
   1.172 +                                               uint32 desired_access,
   1.173 +                                               HANDLE* handle) {
   1.174 +  *handle = NULL;
   1.175 +  NtOpenProcessTokenFunction NtOpenProcessToken = NULL;
   1.176 +  ResolveNTFunctionPtr("NtOpenProcessToken", &NtOpenProcessToken);
   1.177 +
   1.178 +  if (CURRENT_PROCESS != process)
   1.179 +    return STATUS_ACCESS_DENIED;
   1.180 +
   1.181 +  HANDLE local_handle;
   1.182 +  NTSTATUS status = NtOpenProcessToken(client_info.process, desired_access,
   1.183 +                                       &local_handle);
   1.184 +  if (NT_SUCCESS(status)) {
   1.185 +    if (!::DuplicateHandle(::GetCurrentProcess(), local_handle,
   1.186 +                           client_info.process, handle, 0, FALSE,
   1.187 +                           DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
   1.188 +      ::CloseHandle(local_handle);
   1.189 +      return STATUS_ACCESS_DENIED;
   1.190 +    }
   1.191 +  }
   1.192 +  return status;
   1.193 +}
   1.194 +
   1.195 +NTSTATUS ProcessPolicy::OpenProcessTokenExAction(const ClientInfo& client_info,
   1.196 +                                                 HANDLE process,
   1.197 +                                                 uint32 desired_access,
   1.198 +                                                 uint32 attributes,
   1.199 +                                                 HANDLE* handle) {
   1.200 +  *handle = NULL;
   1.201 +  NtOpenProcessTokenExFunction NtOpenProcessTokenEx = NULL;
   1.202 +  ResolveNTFunctionPtr("NtOpenProcessTokenEx", &NtOpenProcessTokenEx);
   1.203 +
   1.204 +  if (CURRENT_PROCESS != process)
   1.205 +    return STATUS_ACCESS_DENIED;
   1.206 +
   1.207 +  HANDLE local_handle;
   1.208 +  NTSTATUS status = NtOpenProcessTokenEx(client_info.process, desired_access,
   1.209 +                                         attributes, &local_handle);
   1.210 +  if (NT_SUCCESS(status)) {
   1.211 +    if (!::DuplicateHandle(::GetCurrentProcess(), local_handle,
   1.212 +                           client_info.process, handle, 0, FALSE,
   1.213 +                           DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
   1.214 +      ::CloseHandle(local_handle);
   1.215 +      return STATUS_ACCESS_DENIED;
   1.216 +    }
   1.217 +  }
   1.218 +  return status;
   1.219 +}
   1.220 +
   1.221 +DWORD ProcessPolicy::CreateProcessWAction(EvalResult eval_result,
   1.222 +                                          const ClientInfo& client_info,
   1.223 +                                          const std::wstring &app_name,
   1.224 +                                          const std::wstring &command_line,
   1.225 +                                          PROCESS_INFORMATION* process_info) {
   1.226 +  // The only action supported is ASK_BROKER which means create the process.
   1.227 +  if (GIVE_ALLACCESS != eval_result && GIVE_READONLY != eval_result) {
   1.228 +    return ERROR_ACCESS_DENIED;
   1.229 +  }
   1.230 +
   1.231 +  STARTUPINFO startup_info = {0};
   1.232 +  startup_info.cb = sizeof(startup_info);
   1.233 +  scoped_ptr_malloc<wchar_t> cmd_line(_wcsdup(command_line.c_str()));
   1.234 +
   1.235 +  BOOL should_give_full_access = (GIVE_ALLACCESS == eval_result);
   1.236 +  if (!CreateProcessExWHelper(client_info.process, should_give_full_access,
   1.237 +                              app_name.c_str(), cmd_line.get(), NULL, NULL,
   1.238 +                              FALSE, 0, NULL, NULL, &startup_info,
   1.239 +                              process_info)) {
   1.240 +    return ERROR_ACCESS_DENIED;
   1.241 +  }
   1.242 +  return ERROR_SUCCESS;
   1.243 +}
   1.244 +
   1.245 +}  // namespace sandbox

mercurial