security/sandbox/win/src/process_thread_dispatcher.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 // Copyright (c) 2006-2010 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/process_thread_dispatcher.h"
     7 #include "base/basictypes.h"
     8 #include "base/logging.h"
     9 #include "sandbox/win/src/crosscall_client.h"
    10 #include "sandbox/win/src/interception.h"
    11 #include "sandbox/win/src/interceptors.h"
    12 #include "sandbox/win/src/ipc_tags.h"
    13 #include "sandbox/win/src/policy_broker.h"
    14 #include "sandbox/win/src/policy_params.h"
    15 #include "sandbox/win/src/process_thread_interception.h"
    16 #include "sandbox/win/src/process_thread_policy.h"
    17 #include "sandbox/win/src/sandbox.h"
    19 namespace {
    21 // Extracts the application name from a command line.
    22 //
    23 // The application name is the first element of the command line. If
    24 // there is no quotes, the first element is delimited by the first space.
    25 // If there are quotes, the first element is delimited by the quotes.
    26 //
    27 // The create process call is smarter than us. It tries really hard to launch
    28 // the process even if the command line is wrong. For example:
    29 // "c:\program files\test param" will first try to launch c:\program.exe then
    30 // c:\program files\test.exe. We don't do that, we stop after at the first
    31 // space when there is no quotes.
    32 std::wstring GetPathFromCmdLine(const std::wstring &cmd_line) {
    33   std::wstring exe_name;
    34   // Check if it starts with '"'.
    35   if (cmd_line[0] == L'\"') {
    36     // Find the position of the second '"', this terminates the path.
    37     std::wstring::size_type pos = cmd_line.find(L'\"', 1);
    38     if (std::wstring::npos == pos)
    39       return cmd_line;
    40     exe_name = cmd_line.substr(1, pos - 1);
    41   } else {
    42     // There is no '"', that means that the appname is terminated at the
    43     // first space.
    44     std::wstring::size_type pos = cmd_line.find(L' ');
    45     if (std::wstring::npos == pos) {
    46       // There is no space, the cmd_line contains only the app_name
    47       exe_name = cmd_line;
    48     } else {
    49       exe_name = cmd_line.substr(0, pos);
    50     }
    51   }
    53   return exe_name;
    54 }
    56 // Returns true is the path in parameter is relative. False if it's
    57 // absolute.
    58 bool IsPathRelative(const std::wstring &path) {
    59   // A path is Relative if it's not a UNC path beginnning with \\ or a
    60   // path beginning with a drive. (i.e. X:\)
    61   if (path.find(L"\\\\") == 0 || path.find(L":\\") == 1)
    62     return false;
    63   return true;
    64 }
    66 // Converts a relative path to an absolute path.
    67 bool ConvertToAbsolutePath(const std::wstring& child_current_directory,
    68                            bool use_env_path, std::wstring *path) {
    69   wchar_t file_buffer[MAX_PATH];
    70   wchar_t *file_part = NULL;
    72   // Here we should start by looking at the path where the child application was
    73   // started. We don't have this information yet.
    74   DWORD result = 0;
    75   if (use_env_path) {
    76     // Try with the complete path
    77     result = ::SearchPath(NULL, path->c_str(), NULL, MAX_PATH, file_buffer,
    78                           &file_part);
    79   }
    81   if (0 == result) {
    82     // Try with the current directory of the child
    83     result = ::SearchPath(child_current_directory.c_str(), path->c_str(), NULL,
    84                           MAX_PATH, file_buffer, &file_part);
    85   }
    87   if (0 == result || result >= MAX_PATH)
    88     return false;
    90   *path = file_buffer;
    91   return true;
    92 }
    94 }  // namespace
    95 namespace sandbox {
    97 ThreadProcessDispatcher::ThreadProcessDispatcher(PolicyBase* policy_base)
    98     : policy_base_(policy_base) {
    99   static const IPCCall open_thread = {
   100     {IPC_NTOPENTHREAD_TAG, ULONG_TYPE, ULONG_TYPE},
   101     reinterpret_cast<CallbackGeneric>(
   102         &ThreadProcessDispatcher::NtOpenThread)
   103   };
   105   static const IPCCall open_process = {
   106     {IPC_NTOPENPROCESS_TAG, ULONG_TYPE, ULONG_TYPE},
   107     reinterpret_cast<CallbackGeneric>(
   108         &ThreadProcessDispatcher::NtOpenProcess)
   109   };
   111   static const IPCCall process_token = {
   112     {IPC_NTOPENPROCESSTOKEN_TAG, VOIDPTR_TYPE, ULONG_TYPE},
   113     reinterpret_cast<CallbackGeneric>(
   114         &ThreadProcessDispatcher::NtOpenProcessToken)
   115   };
   117   static const IPCCall process_tokenex = {
   118     {IPC_NTOPENPROCESSTOKENEX_TAG, VOIDPTR_TYPE, ULONG_TYPE, ULONG_TYPE},
   119     reinterpret_cast<CallbackGeneric>(
   120         &ThreadProcessDispatcher::NtOpenProcessTokenEx)
   121   };
   123   static const IPCCall create_params = {
   124     {IPC_CREATEPROCESSW_TAG, WCHAR_TYPE, WCHAR_TYPE, WCHAR_TYPE, INOUTPTR_TYPE},
   125     reinterpret_cast<CallbackGeneric>(
   126         &ThreadProcessDispatcher::CreateProcessW)
   127   };
   129   ipc_calls_.push_back(open_thread);
   130   ipc_calls_.push_back(open_process);
   131   ipc_calls_.push_back(process_token);
   132   ipc_calls_.push_back(process_tokenex);
   133   ipc_calls_.push_back(create_params);
   134 }
   136 bool ThreadProcessDispatcher::SetupService(InterceptionManager* manager,
   137                                            int service) {
   138   switch (service) {
   139     case IPC_NTOPENTHREAD_TAG:
   140     case IPC_NTOPENPROCESS_TAG:
   141     case IPC_NTOPENPROCESSTOKEN_TAG:
   142     case IPC_NTOPENPROCESSTOKENEX_TAG:
   143       // There is no explicit policy for these services.
   144       NOTREACHED();
   145       return false;
   147     case IPC_CREATEPROCESSW_TAG:
   148       return INTERCEPT_EAT(manager, L"kernel32.dll", CreateProcessW,
   149                            CREATE_PROCESSW_ID, 44) &&
   150              INTERCEPT_EAT(manager, L"kernel32.dll", CreateProcessA,
   151                            CREATE_PROCESSA_ID, 44);
   153     default:
   154       return false;
   155   }
   156 }
   158 bool ThreadProcessDispatcher::NtOpenThread(IPCInfo* ipc, DWORD desired_access,
   159                                            DWORD thread_id) {
   160   HANDLE handle;
   161   NTSTATUS ret = ProcessPolicy::OpenThreadAction(*ipc->client_info,
   162                                                  desired_access, thread_id,
   163                                                  &handle);
   164   ipc->return_info.nt_status = ret;
   165   ipc->return_info.handle = handle;
   166   return true;
   167 }
   169 bool ThreadProcessDispatcher::NtOpenProcess(IPCInfo* ipc, DWORD desired_access,
   170                                             DWORD process_id) {
   171   HANDLE handle;
   172   NTSTATUS ret = ProcessPolicy::OpenProcessAction(*ipc->client_info,
   173                                                   desired_access, process_id,
   174                                                   &handle);
   175   ipc->return_info.nt_status = ret;
   176   ipc->return_info.handle = handle;
   177   return true;
   178 }
   180 bool ThreadProcessDispatcher::NtOpenProcessToken(IPCInfo* ipc, HANDLE process,
   181                                                  DWORD desired_access) {
   182   HANDLE handle;
   183   NTSTATUS ret = ProcessPolicy::OpenProcessTokenAction(*ipc->client_info,
   184                                                        process, desired_access,
   185                                                        &handle);
   186   ipc->return_info.nt_status = ret;
   187   ipc->return_info.handle = handle;
   188   return true;
   189 }
   191 bool ThreadProcessDispatcher::NtOpenProcessTokenEx(IPCInfo* ipc, HANDLE process,
   192                                                    DWORD desired_access,
   193                                                    DWORD attributes) {
   194   HANDLE handle;
   195   NTSTATUS ret = ProcessPolicy::OpenProcessTokenExAction(*ipc->client_info,
   196                                                          process,
   197                                                          desired_access,
   198                                                          attributes, &handle);
   199   ipc->return_info.nt_status = ret;
   200   ipc->return_info.handle = handle;
   201   return true;
   202 }
   204 bool ThreadProcessDispatcher::CreateProcessW(IPCInfo* ipc, std::wstring* name,
   205                                              std::wstring* cmd_line,
   206                                              std::wstring* cur_dir,
   207                                              CountedBuffer* info) {
   208   if (sizeof(PROCESS_INFORMATION) != info->Size())
   209     return false;
   211   // Check if there is an application name.
   212   std::wstring exe_name;
   213   if (!name->empty())
   214     exe_name = *name;
   215   else
   216     exe_name = GetPathFromCmdLine(*cmd_line);
   218   if (IsPathRelative(exe_name)) {
   219     if (!ConvertToAbsolutePath(*cur_dir, name->empty(), &exe_name)) {
   220       // Cannot find the path. Maybe the file does not exist.
   221       ipc->return_info.win32_result = ERROR_FILE_NOT_FOUND;
   222       return true;
   223     }
   224   }
   226   const wchar_t* const_exe_name = exe_name.c_str();
   227   CountedParameterSet<NameBased> params;
   228   params[NameBased::NAME] = ParamPickerMake(const_exe_name);
   230   EvalResult eval = policy_base_->EvalPolicy(IPC_CREATEPROCESSW_TAG,
   231                                              params.GetBase());
   233   PROCESS_INFORMATION* proc_info =
   234       reinterpret_cast<PROCESS_INFORMATION*>(info->Buffer());
   235   // Here we force the app_name to be the one we used for the policy lookup.
   236   // If our logic was wrong, at least we wont allow create a random process.
   237   DWORD ret = ProcessPolicy::CreateProcessWAction(eval, *ipc->client_info,
   238                                                   exe_name, *cmd_line,
   239                                                   proc_info);
   241   ipc->return_info.win32_result = ret;
   242   return true;
   243 }
   245 }  // namespace sandbox

mercurial