15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/tests/common/controller.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/process/process.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/sys_string_conversions.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/sandbox_factory.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kDefaultTimeout = 60000;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Constructs a full path to a file inside the system32 folder.
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 MakePathToSys32(const wchar_t* name, bool is_obj_man_path) {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wchar_t windows_path[MAX_PATH] = {0};
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (0 == ::GetSystemWindowsDirectoryW(windows_path, MAX_PATH))
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return base::string16();
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::string16 full_path(windows_path);
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (full_path.empty())
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return full_path;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_obj_man_path)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    full_path.insert(0, L"\\??\\");
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  full_path += L"\\system32\\";
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  full_path += name;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return full_path;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Constructs a full path to a file inside the syswow64 folder.
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 MakePathToSysWow64(const wchar_t* name, bool is_obj_man_path) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wchar_t windows_path[MAX_PATH] = {0};
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (0 == ::GetSystemWindowsDirectoryW(windows_path, MAX_PATH))
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return base::string16();
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::string16 full_path(windows_path);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (full_path.empty())
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return full_path;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_obj_man_path)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    full_path.insert(0, L"\\??\\");
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  full_path += L"\\SysWOW64\\";
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  full_path += name;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return full_path;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsProcessRunning(HANDLE process) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD exit_code = 0;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (::GetExitCodeProcess(process, &exit_code))
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return exit_code == STILL_ACTIVE;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sandbox {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 MakePathToSys(const wchar_t* name, bool is_obj_man_path) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (base::win::OSInfo::GetInstance()->wow64_status() ==
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::win::OSInfo::WOW64_ENABLED) ?
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MakePathToSysWow64(name, is_obj_man_path) :
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MakePathToSys32(name, is_obj_man_path);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrokerServices* GetBroker() {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static BrokerServices* broker = SandboxFactory::GetBrokerServices();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool is_initialized = false;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!broker) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_initialized) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (SBOX_ALL_OK != broker->Init())
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_initialized = true;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return broker;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TestRunner::TestRunner(JobLevel job_level, TokenLevel startup_token,
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       TokenLevel main_token)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : is_init_(false), is_async_(false), no_sandbox_(false),
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      target_process_id_(0) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Init(job_level, startup_token, main_token);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TestRunner::TestRunner()
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : is_init_(false), is_async_(false), no_sandbox_(false),
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      target_process_id_(0) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Init(JOB_LOCKDOWN, USER_RESTRICTED_SAME_ACCESS, USER_LOCKDOWN);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestRunner::Init(JobLevel job_level, TokenLevel startup_token,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      TokenLevel main_token) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  broker_ = NULL;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  policy_ = NULL;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timeout_ = kDefaultTimeout;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = AFTER_REVERT;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_async_= false;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kill_on_destruction_ = true;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target_process_id_ = 0;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  broker_ = GetBroker();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!broker_)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  policy_ = broker_->CreatePolicy();
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!policy_)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  policy_->SetJobLevel(job_level, 0);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  policy_->SetTokenLevel(startup_token, main_token);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_init_ = true;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TargetPolicy* TestRunner::GetPolicy() {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return policy_;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TestRunner::~TestRunner() {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (target_process_ && kill_on_destruction_)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::TerminateProcess(target_process_, 0);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (policy_)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    policy_->Release();
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TestRunner::AddRule(TargetPolicy::SubSystem subsystem,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         TargetPolicy::Semantics semantics,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const wchar_t* pattern) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_init_)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (SBOX_ALL_OK == policy_->AddRule(subsystem, semantics, pattern));
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TestRunner::AddRuleSys32(TargetPolicy::Semantics semantics,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const wchar_t* pattern) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_init_)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::string16 win32_path = MakePathToSys32(pattern, false);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (win32_path.empty())
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!AddRule(TargetPolicy::SUBSYS_FILES, semantics, win32_path.c_str()))
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base::win::OSInfo::GetInstance()->wow64_status() !=
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::win::OSInfo::WOW64_ENABLED)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  win32_path = MakePathToSysWow64(pattern, false);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (win32_path.empty())
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AddRule(TargetPolicy::SUBSYS_FILES, semantics, win32_path.c_str());
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TestRunner::AddFsRule(TargetPolicy::Semantics semantics,
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const wchar_t* pattern) {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_init_)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AddRule(TargetPolicy::SUBSYS_FILES, semantics, pattern);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TestRunner::RunTest(const wchar_t* command) {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (MAX_STATE > 10)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_INVALID_PARAMETER;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wchar_t state_number[2];
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_number[0] = L'0' + state_;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_number[1] = L'\0';
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::string16 full_command(state_number);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  full_command += L" ";
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  full_command += command;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return InternalRunTest(full_command.c_str());
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TestRunner::InternalRunTest(const wchar_t* command) {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_init_)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_FAILED_TO_RUN_TEST;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For simplicity TestRunner supports only one process per instance.
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (target_process_) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IsProcessRunning(target_process_))
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SBOX_TEST_FAILED_TO_RUN_TEST;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    target_process_.Close();
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    target_process_id_ = 0;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the path to the sandboxed process.
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wchar_t prog_name[MAX_PATH];
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetModuleFileNameW(NULL, prog_name, MAX_PATH);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Launch the sandboxed process.
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResultCode result = SBOX_ALL_OK;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PROCESS_INFORMATION target = {0};
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::string16 arguments(L"\"");
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  arguments += prog_name;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  arguments += L"\" -child";
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  arguments += no_sandbox_ ? L"-no-sandbox " : L" ";
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  arguments += command;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (no_sandbox_) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STARTUPINFO startup_info = {sizeof(STARTUPINFO)};
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!::CreateProcessW(prog_name, &arguments[0], NULL, NULL, FALSE, 0,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          NULL, NULL, &startup_info, &target)) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SBOX_ERROR_GENERIC;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    broker_->AddTargetPeer(target.hProcess);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = broker_->SpawnTarget(prog_name, arguments.c_str(), policy_,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  &target);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (SBOX_ALL_OK != result)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_FAILED_TO_RUN_TEST;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::ResumeThread(target.hThread);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For an asynchronous run we don't bother waiting.
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_async_) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    target_process_.Set(target.hProcess);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    target_process_id_ = target.dwProcessId;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::CloseHandle(target.hThread);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_SUCCEEDED;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (::IsDebuggerPresent()) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Don't kill the target process on a time-out while we are debugging.
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    timeout_ = INFINITE;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (WAIT_TIMEOUT == ::WaitForSingleObject(target.hProcess, timeout_)) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::TerminateProcess(target.hProcess, SBOX_TEST_TIMED_OUT);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::CloseHandle(target.hProcess);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::CloseHandle(target.hThread);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_TIMED_OUT;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD exit_code = SBOX_TEST_LAST_RESULT;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!::GetExitCodeProcess(target.hProcess, &exit_code)) {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::CloseHandle(target.hProcess);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::CloseHandle(target.hThread);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_FAILED_TO_RUN_TEST;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::CloseHandle(target.hProcess);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::CloseHandle(target.hThread);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return exit_code;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestRunner::SetTimeout(DWORD timeout_ms) {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timeout_ = timeout_ms;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestRunner::SetTestState(SboxTestsState desired_state) {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = desired_state;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is the main procedure for the target (child) application. We'll find out
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the target test and call it.
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We expect the arguments to be:
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  argv[1] = "-child"
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  argv[2] = SboxTestsState when to run the command
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  argv[3] = command to run
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  argv[4...] = command arguments.
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int DispatchCall(int argc, wchar_t **argv) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (argc < 4)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_INVALID_PARAMETER;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We hard code two tests to avoid dispatch failures.
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (0 == _wcsicmp(argv[3], L"wait")) {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Sleep(INFINITE);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SBOX_TEST_TIMED_OUT;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (0 == _wcsicmp(argv[3], L"ping"))
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SBOX_TEST_PING_OK;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SboxTestsState state = static_cast<SboxTestsState>(_wtoi(argv[2]));
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((state <= MIN_STATE) || (state >= MAX_STATE))
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_INVALID_PARAMETER;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HMODULE module;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         reinterpret_cast<wchar_t*>(&DispatchCall), &module))
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string command_name = base::SysWideToMultiByte(argv[3], CP_UTF8);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandFunction command = reinterpret_cast<CommandFunction>(
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                ::GetProcAddress(module, command_name.c_str()));
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!command)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (BEFORE_INIT == state)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return command(argc - 4, argv + 4);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (EVERY_STATE == state)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command(argc - 4, argv + 4);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TargetServices* target = SandboxFactory::GetTargetServices();
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (target) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (SBOX_ALL_OK != target->Init())
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (BEFORE_REVERT == state)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return command(argc - 4, argv + 4);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (EVERY_STATE == state)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command(argc - 4, argv + 4);
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    target->LowerToken();
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (0 != _wcsicmp(argv[1], L"-child-no-sandbox")) {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command(argc - 4, argv + 4);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace sandbox
337