Add support for alternate window station.

TEST: Start chrome, make sure it loads pages, then user process explorer to make sure the WindowStation handle name is not the same as the browser process.

BUG:10996

Review URL: http://codereview.chromium.org/113190

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16483 0039d316-1c4b-4281-b951-d872f2087c98
Esse commit está contido em:
nsylvain@chromium.org
2009-05-20 16:05:56 +00:00
commit dbe6ca45dc
20 arquivos alterados com 502 adições e 69 exclusões
+22 -6
Ver Arquivo
@@ -1,4 +1,4 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -291,6 +291,27 @@ int BrowserMain(const MainFunctionParams& parameters) {
// BrowserProcessImpl's constructor should set g_browser_process.
DCHECK(g_browser_process);
#if defined(OS_WIN)
// IMPORTANT: This piece of code needs to run as early as possible in the
// process because it will initialize the sandbox broker, which requires the
// process to swap its window station. During this time all the UI will be
// broken. This has to run before threads and windows are created.
sandbox::BrokerServices* broker_services =
parameters.sandbox_info_.BrokerServices();
if (broker_services) {
browser_process->InitBrokerServices(broker_services);
if (!parsed_command_line.HasSwitch(switches::kNoSandbox)) {
bool use_winsta = !parsed_command_line.HasSwitch(
switches::kDisableAltWinstation);
// Precreate the desktop and window station used by the renderers.
sandbox::TargetPolicy* policy = broker_services->CreatePolicy();
sandbox::ResultCode result = policy->CreateAlternateDesktop(use_winsta);
CHECK(sandbox::SBOX_ERROR_FAILED_TO_SWITCH_BACK_WINSTATION != result);
policy->Release();
}
}
#endif
std::wstring local_state_path;
PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path);
bool local_state_file_exists = file_util::PathExists(local_state_path);
@@ -573,11 +594,6 @@ int BrowserMain(const MainFunctionParams& parameters) {
#if defined(OS_WIN)
RegisterExtensionProtocols();
sandbox::BrokerServices* broker_services =
parameters.sandbox_info_.BrokerServices();
if (broker_services)
browser_process->InitBrokerServices(broker_services);
#endif
// In unittest mode, this will do nothing. In normal mode, this will create
+11 -16
Ver Arquivo
@@ -1,4 +1,4 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -27,8 +27,6 @@
namespace {
const wchar_t* const kDesktopName = L"ChromeRendererDesktop";
// The DLLs listed here are known (or under strong suspicion) of causing crashes
// when they are loaded in the renderer.
const wchar_t* const kTroublesomeDlls[] = {
@@ -315,7 +313,8 @@ bool AddPolicyForPlugin(const CommandLine* cmd_line,
return false;
}
void AddPolicyForRenderer(HDESK desktop, sandbox::TargetPolicy* policy) {
void AddPolicyForRenderer(sandbox::TargetPolicy* policy,
bool* on_sandbox_desktop) {
policy->SetJobLevel(sandbox::JOB_LOCKDOWN, 0);
sandbox::TokenLevel initial_token = sandbox::USER_UNPROTECTED;
@@ -328,9 +327,13 @@ void AddPolicyForRenderer(HDESK desktop, sandbox::TargetPolicy* policy) {
policy->SetTokenLevel(initial_token, sandbox::USER_LOCKDOWN);
policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
if (desktop) {
policy->SetDesktop(kDesktopName);
bool use_winsta = !CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableAltWinstation);
if (sandbox::SBOX_ALL_OK == policy->SetAlternateDesktop(use_winsta)) {
*on_sandbox_desktop = true;
} else {
*on_sandbox_desktop = false;
DLOG(WARNING) << "Failed to apply desktop security to the renderer";
}
@@ -391,14 +394,12 @@ base::ProcessHandle StartProcessWithAccess(CommandLine* cmd_line,
PROCESS_INFORMATION target = {0};
sandbox::TargetPolicy* policy = broker_service->CreatePolicy();
HDESK desktop = NULL;
bool on_sandbox_desktop = false;
if (type == ChildProcessInfo::PLUGIN_PROCESS) {
if (!AddPolicyForPlugin(cmd_line, policy))
return 0;
} else {
desktop = CreateDesktop(
kDesktopName, NULL, NULL, 0, DESKTOP_CREATEWINDOW, NULL);
AddPolicyForRenderer(desktop, policy);
AddPolicyForRenderer(policy, &on_sandbox_desktop);
}
if (!exposed_dir.empty()) {
@@ -418,8 +419,6 @@ base::ProcessHandle StartProcessWithAccess(CommandLine* cmd_line,
if (!AddGenericPolicy(policy)) {
NOTREACHED();
if (desktop)
CloseDesktop(desktop);
return 0;
}
@@ -429,14 +428,10 @@ base::ProcessHandle StartProcessWithAccess(CommandLine* cmd_line,
policy, &target);
policy->Release();
if (desktop)
CloseDesktop(desktop);
if (sandbox::SBOX_ALL_OK != result)
return 0;
if (type == ChildProcessInfo::RENDER_PROCESS) {
bool on_sandbox_desktop = (desktop != NULL);
NotificationService::current()->Notify(
NotificationType::RENDERER_PROCESS_IN_SBOX,
NotificationService::AllSources(),
+3
Ver Arquivo
@@ -96,6 +96,9 @@ const wchar_t kInProcessPlugins[] = L"in-process-plugins";
// Runs the renderer outside the sandbox.
const wchar_t kNoSandbox[] = L"no-sandbox";
// Disables the alternate window station for the renderer.
const wchar_t kDisableAltWinstation[] = L"disable-winsta";
// Runs the plugin processes inside the sandbox.
const wchar_t kSafePlugins[] = L"safe-plugins";
+4 -3
Ver Arquivo
@@ -4,8 +4,8 @@
// Defines all the command-line switches used by Chrome.
#ifndef CHROME_COMMON_CHROME_SWITCHES_H__
#define CHROME_COMMON_CHROME_SWITCHES_H__
#ifndef CHROME_COMMON_CHROME_SWITCHES_H_
#define CHROME_COMMON_CHROME_SWITCHES_H_
#include "base/base_switches.h"
@@ -35,6 +35,7 @@ extern const wchar_t kProcessPerTab[];
extern const wchar_t kProcessPerSite[];
extern const wchar_t kInProcessPlugins[];
extern const wchar_t kNoSandbox[];
extern const wchar_t kDisableAltWinstation[];
extern const wchar_t kSafePlugins[];
extern const wchar_t kTrustedPlugins[];
extern const wchar_t kTestSandbox[];
@@ -179,4 +180,4 @@ extern const wchar_t kNewNewTabPage[];
} // namespace switches
#endif // CHROME_COMMON_CHROME_SWITCHES_H__
#endif // CHROME_COMMON_CHROME_SWITCHES_H_
@@ -18,15 +18,44 @@ namespace {
// can be done with OpenThemeData() but it fails unless you pass a valid
// window at least the first time. Interestingly, the very act of creating a
// window also sets the connection to the theme service.
void EnableThemeSupportForRenderer() {
void EnableThemeSupportForRenderer(bool no_sandbox) {
HWINSTA current = NULL;
HWINSTA winsta0 = NULL;
if (!no_sandbox) {
current = ::GetProcessWindowStation();
winsta0 = ::OpenWindowStationW(L"WinSta0", FALSE, GENERIC_READ);
if (!winsta0 || !::SetProcessWindowStation(winsta0)) {
// Could not set the alternate window station. There is a possibility
// that the theme wont be correctly initialized on XP.
NOTREACHED() << "Unable to switch to WinSt0";
}
}
HWND window = ::CreateWindowExW(0, L"Static", L"", WS_POPUP | WS_DISABLED,
CW_USEDEFAULT, 0, 0, 0, HWND_MESSAGE, NULL,
::GetModuleHandleA(NULL), NULL);
if (!window) {
DLOG(WARNING) << "failed to enable theme support";
return;
} else {
::DestroyWindow(window);
}
if (!no_sandbox) {
// Revert the window station.
if (!current || !::SetProcessWindowStation(current)) {
// We failed to switch back to the secure window station. This might
// confuse the renderer enough that we should kill it now.
CHECK(false) << "Failed to restore alternate window station";
}
if (!::CloseWindowStation(winsta0)) {
// We might be leaking a winsta0 handle. This is a security risk, but
// since we allow fail over to no desktop protection in low memory
// condition, this is not a big risk.
NOTREACHED();
}
}
::DestroyWindow(window);
}
} // namespace
@@ -43,7 +72,9 @@ RendererMainPlatformDelegate::~RendererMainPlatformDelegate() {
void RendererMainPlatformDelegate::PlatformInitialize() {
// Be mindful of what resources you acquire here. They can be used by
// malicious code if the renderer gets compromised.
EnableThemeSupportForRenderer();
const CommandLine& command_line = parameters_.command_line_;
bool no_sandbox = command_line.HasSwitch(switches::kNoSandbox);
EnableThemeSupportForRenderer(no_sandbox);
}
void RendererMainPlatformDelegate::PlatformUninitialize() {
+2
Ver Arquivo
@@ -134,6 +134,8 @@
'src/win2k_threadpool.h',
'src/win_utils.cc',
'src/win_utils.h',
'src/window.h',
'src/window.cc',
# Precompiled headers.
'src/stdafx.cc',
+2 -2
Ver Arquivo
@@ -1,4 +1,4 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -509,7 +509,7 @@ bool MainUIWindow::SpawnTarget() {
policy->SetJobLevel(sandbox::JOB_LOCKDOWN, 0);
policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
sandbox::USER_LOCKDOWN);
policy->SetDesktop(L"random_desktop_name");
policy->SetAlternateDesktop(true);
policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
// Set the rule to allow the POC dll to be loaded by the target. Note that
+9 -1
Ver Arquivo
@@ -1,4 +1,4 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -13,6 +13,14 @@ void POCDLL_API TestSpyKeys(HANDLE log) {
HandleToFile handle2file;
FILE *output = handle2file.Translate(log, "w");
if (RegisterHotKey(NULL, 1, 0, 0x42)) {
fprintf(output, "[GRANTED] successfully registered hotkey\r\n");
UnregisterHotKey(NULL, 1);
} else {
fprintf(output, "[BLOCKED] Failed to register hotkey. Error = %d\r\n",
::GetLastError());
}
fprintf(output, "[INFO] Logging keystrokes for 15 seconds\r\n");
fflush(output);
std::wstring logged;
+3 -2
Ver Arquivo
@@ -1,4 +1,4 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -256,7 +256,8 @@ ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path,
TargetProcess* target = new TargetProcess(initial_token, lockdown_token,
job, thread_pool_);
std::wstring desktop = policy_base->GetDesktop();
std::wstring desktop = policy_base->GetAlternateDesktop();
win_result = target->Create(exe_path, command_line,
desktop.empty() ? NULL : desktop.c_str(),
&process_info);
+82 -6
Ver Arquivo
@@ -1,4 +1,4 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -165,6 +165,12 @@ TEST(PolicyTargetTest, OpenProcess) {
// current desktop.
TEST(PolicyTargetTest, DesktopPolicy) {
BrokerServices* broker = GetBroker();
// Precreate the desktop.
TargetPolicy* temp_policy = broker->CreatePolicy();
temp_policy->CreateAlternateDesktop(false);
temp_policy->Release();
ASSERT_TRUE(broker != NULL);
// Get the path to the sandboxed app.
@@ -180,7 +186,7 @@ TEST(PolicyTargetTest, DesktopPolicy) {
PROCESS_INFORMATION target = {0};
TargetPolicy* policy = broker->CreatePolicy();
policy->SetDesktop(L"desktop_for_sbox");
policy->SetAlternateDesktop(false);
policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN);
result = broker->SpawnTarget(prog_name, arguments.c_str(), policy, &target);
policy->Release();
@@ -194,7 +200,8 @@ TEST(PolicyTargetTest, DesktopPolicy) {
EXPECT_NE(::GetThreadDesktop(target.dwThreadId),
::GetThreadDesktop(::GetCurrentThreadId()));
HDESK desk = ::OpenDesktop(L"desktop_for_sbox", 0, FALSE, DESKTOP_ENUMERATE);
std::wstring desktop_name = policy->GetAlternateDesktop();
HDESK desk = ::OpenDesktop(desktop_name.c_str(), 0, FALSE, DESKTOP_ENUMERATE);
EXPECT_TRUE(NULL != desk);
EXPECT_TRUE(::CloseDesktop(desk));
EXPECT_TRUE(::TerminateProcess(target.hProcess, 0));
@@ -204,11 +211,80 @@ TEST(PolicyTargetTest, DesktopPolicy) {
EXPECT_TRUE(::CloseHandle(target.hProcess));
EXPECT_TRUE(::CloseHandle(target.hThread));
// Wait for the desktop to be deleted by the destructor of TargetProcess
Sleep(2000);
// Close the desktop handle.
temp_policy = broker->CreatePolicy();
temp_policy->DestroyAlternateDesktop();
temp_policy->Release();
desk = ::OpenDesktop(L"desktop_for_sbox", 0, FALSE, DESKTOP_ENUMERATE);
// Make sure the desktop does not exist anymore.
desk = ::OpenDesktop(desktop_name.c_str(), 0, FALSE, DESKTOP_ENUMERATE);
EXPECT_TRUE(NULL == desk);
}
// Launches the app in the sandbox and ask it to wait in an
// infinite loop. Waits for 2 seconds and then check if the
// winstation associated with the app thread is not the same as the
// current desktop.
TEST(PolicyTargetTest, WinstaPolicy) {
BrokerServices* broker = GetBroker();
// Precreate the desktop.
TargetPolicy* temp_policy = broker->CreatePolicy();
temp_policy->CreateAlternateDesktop(true);
temp_policy->Release();
ASSERT_TRUE(broker != NULL);
// Get the path to the sandboxed app.
wchar_t prog_name[MAX_PATH];
GetModuleFileNameW(NULL, prog_name, MAX_PATH);
std::wstring arguments(L"\"");
arguments += prog_name;
arguments += L"\" -child 0 wait"; // Don't care about the "state" argument.
// Launch the app.
ResultCode result = SBOX_ALL_OK;
PROCESS_INFORMATION target = {0};
TargetPolicy* policy = broker->CreatePolicy();
policy->SetAlternateDesktop(true);
policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN);
result = broker->SpawnTarget(prog_name, arguments.c_str(), policy, &target);
policy->Release();
EXPECT_EQ(SBOX_ALL_OK, result);
EXPECT_EQ(1, ::ResumeThread(target.hThread));
EXPECT_EQ(WAIT_TIMEOUT, ::WaitForSingleObject(target.hProcess, 2000));
EXPECT_NE(::GetThreadDesktop(target.dwThreadId),
::GetThreadDesktop(::GetCurrentThreadId()));
std::wstring desktop_name = policy->GetAlternateDesktop();
ASSERT_FALSE(desktop_name.empty());
// Make sure there is a backslash, for the window station name.
EXPECT_NE(desktop_name.find_first_of(L'\\'), std::wstring::npos);
// Isolate the desktop name.
desktop_name = desktop_name.substr(desktop_name.find_first_of(L'\\') + 1);
HDESK desk = ::OpenDesktop(desktop_name.c_str(), 0, FALSE, DESKTOP_ENUMERATE);
// This should fail if the desktop is really on another window station.
EXPECT_FALSE(NULL != desk);
EXPECT_TRUE(::TerminateProcess(target.hProcess, 0));
::WaitForSingleObject(target.hProcess, INFINITE);
EXPECT_TRUE(::CloseHandle(target.hProcess));
EXPECT_TRUE(::CloseHandle(target.hThread));
// Close the desktop handle.
temp_policy = broker->CreatePolicy();
temp_policy->DestroyAlternateDesktop();
temp_policy->Release();
}
} // namespace sandbox
+8
Ver Arquivo
@@ -183,6 +183,14 @@
RelativePath=".\sid.h"
>
</File>
<File
RelativePath=".\window.cc"
>
</File>
<File
RelativePath=".\window.h"
>
</File>
</Filter>
<Filter
Name="Interception"
+17 -3
Ver Arquivo
@@ -1,10 +1,12 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SANDBOX_SRC_SANDBOX_POLICY_H_
#define SANDBOX_SRC_SANDBOX_POLICY_H_
#include <string>
#include "base/basictypes.h"
#include "sandbox/src/sandbox_types.h"
#include "sandbox/src/security_level.h"
@@ -80,8 +82,20 @@ class TargetPolicy {
virtual ResultCode SetJobLevel(JobLevel job_level, uint32 ui_exceptions) = 0;
// Specifies the desktop on which the application is going to run. If the
// desktop does not exist, it will be created.
virtual ResultCode SetDesktop(const wchar_t* desktop) = 0;
// desktop does not exist, it will be created. If alternate_winstation is
// set to true, the desktop will be created on an alternate window station.
virtual ResultCode SetAlternateDesktop(bool alternate_winstation) = 0;
// Returns the name of the alternate desktop used. If an alternate window
// station is specified, the name is prepended by the window station name,
// followed by a backslash.
virtual std::wstring GetAlternateDesktop() const = 0;
// Precreates the desktop and window station, if any.
virtual ResultCode CreateAlternateDesktop(bool alternate_winstation) = 0;
// Destroys the desktop and windows station.
virtual void DestroyAlternateDesktop() = 0;
// Sets the integrity level of the process in the sandbox. The integrity level
// will not take effect before you call LowerToken. User Interface Privilege
+84 -2
Ver Arquivo
@@ -1,4 +1,4 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -24,6 +24,7 @@
#include "sandbox/src/sync_dispatcher.h"
#include "sandbox/src/sync_policy.h"
#include "sandbox/src/target_process.h"
#include "sandbox/src/window.h"
namespace {
// The standard windows size for one memory page.
@@ -48,6 +49,10 @@ namespace sandbox {
SANDBOX_INTERCEPT IntegrityLevel g_shared_delayed_integrity_level;
// Initializes static members.
HWINSTA PolicyBase::alternate_winstation_handle_ = NULL;
HDESK PolicyBase::alternate_desktop_handle_ = NULL;
PolicyBase::PolicyBase()
: ref_count(1),
lockdown_level_(USER_LOCKDOWN),
@@ -58,7 +63,9 @@ PolicyBase::PolicyBase()
policy_(NULL),
policy_maker_(NULL),
file_system_init_(false),
relaxed_interceptions_(true) {
relaxed_interceptions_(true),
use_alternate_desktop_(false),
use_alternate_winstation_(false) {
::InitializeCriticalSection(&lock_);
// Initialize the IPC dispatcher array.
memset(&ipc_targets_, NULL, sizeof(ipc_targets_));
@@ -132,6 +139,81 @@ DWORD PolicyBase::MakeTokens(HANDLE* initial, HANDLE* lockdown) {
return SBOX_ALL_OK;
}
std::wstring PolicyBase::GetAlternateDesktop() const {
// No alternate desktop or winstation. Return an empty string.
if (!use_alternate_desktop_ && !use_alternate_winstation_) {
return std::wstring();
}
// The desktop and winstation should have been created by now.
// If we hit this scenario, it means that the user ignored the failure
// during SetAlternateDesktop, so we ignore it here too.
if (use_alternate_desktop_ && !alternate_desktop_handle_) {
return std::wstring();
}
if (use_alternate_winstation_ && (!alternate_desktop_handle_ ||
!alternate_winstation_handle_)) {
return std::wstring();
}
return GetFullDesktopName(alternate_winstation_handle_,
alternate_desktop_handle_);
}
ResultCode PolicyBase::CreateAlternateDesktop(bool alternate_winstation) {
if (alternate_winstation) {
// Previously called with alternate_winstation = false?
if (!alternate_winstation_handle_ && alternate_desktop_handle_)
return SBOX_ERROR_UNSUPPORTED;
// Check if it's already created.
if (alternate_winstation_handle_ && alternate_desktop_handle_)
return SBOX_ALL_OK;
DCHECK(!alternate_winstation_handle_);
// Create the window station.
ResultCode result = CreateAltWindowStation(&alternate_winstation_handle_);
if (SBOX_ALL_OK != result)
return result;
// Verify that everything is fine.
if (!alternate_winstation_handle_ ||
GetWindowObjectName(alternate_winstation_handle_).empty())
return SBOX_ERROR_CANNOT_CREATE_DESKTOP;
// Create the destkop.
result = CreateAltDesktop(alternate_winstation_handle_,
&alternate_desktop_handle_);
if (SBOX_ALL_OK != result)
return result;
// Verify that everything is fine.
if (!alternate_desktop_handle_ ||
GetWindowObjectName(alternate_desktop_handle_).empty())
return SBOX_ERROR_CANNOT_CREATE_DESKTOP;
} else {
// Previously called with alternate_winstation = true?
if (alternate_winstation_handle_)
return SBOX_ERROR_UNSUPPORTED;
// Check if it already exists.
if (alternate_desktop_handle_)
return SBOX_ALL_OK;
// Create the destkop.
ResultCode result = CreateAltDesktop(NULL, &alternate_desktop_handle_);
if (SBOX_ALL_OK != result)
return result;
// Verify that everything is fine.
if (!alternate_desktop_handle_ ||
GetWindowObjectName(alternate_desktop_handle_).empty())
return SBOX_ERROR_CANNOT_CREATE_DESKTOP;
}
return SBOX_ALL_OK;
}
bool PolicyBase::AddTarget(TargetProcess* target) {
if (NULL != policy_)
policy_maker_->Done();
+27 -10
Ver Arquivo
@@ -1,11 +1,11 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SANDBOX_SRC_SANDBOX_POLICY_BASE_H_
#define SANDBOX_SRC_SANDBOX_POLICY_BASE_H_
#include <Windows.h>
#include <windows.h>
#include <list>
#include "base/basictypes.h"
@@ -57,9 +57,26 @@ class PolicyBase : public Dispatcher, public TargetPolicy {
return SBOX_ALL_OK;
}
virtual ResultCode SetDesktop(const wchar_t* desktop) {
desktop_ = desktop;
return SBOX_ALL_OK;
virtual ResultCode SetAlternateDesktop(bool alternate_winstation) {
use_alternate_desktop_ = true;
use_alternate_winstation_ = alternate_winstation;
return CreateAlternateDesktop(alternate_winstation);
}
virtual std::wstring GetAlternateDesktop() const;
virtual ResultCode CreateAlternateDesktop(bool alternate_winstation);
virtual void DestroyAlternateDesktop() {
if (alternate_desktop_handle_) {
::CloseDesktop(alternate_desktop_handle_);
alternate_desktop_handle_ = NULL;
}
if (alternate_winstation_handle_) {
::CloseWindowStation(alternate_winstation_handle_);
alternate_winstation_handle_ = NULL;
}
}
virtual ResultCode SetIntegrityLevel(IntegrityLevel integrity_level) {
@@ -84,10 +101,6 @@ class PolicyBase : public Dispatcher, public TargetPolicy {
return SBOX_ALL_OK;
}
std::wstring GetDesktop() const {
return desktop_;
}
// Creates a Job object with the level specified in a previous call to
// SetJobLevel(). Returns the standard windows of ::GetLastError().
DWORD MakeJobObject(HANDLE* job);
@@ -133,7 +146,8 @@ class PolicyBase : public Dispatcher, public TargetPolicy {
TokenLevel initial_level_;
JobLevel job_level_;
uint32 ui_exceptions_;
std::wstring desktop_;
bool use_alternate_desktop_;
bool use_alternate_winstation_;
IntegrityLevel integrity_level_;
IntegrityLevel delayed_integrity_level_;
// The array of objects that will answer IPC calls.
@@ -149,6 +163,9 @@ class PolicyBase : public Dispatcher, public TargetPolicy {
// The list of dlls to unload in the target process.
std::vector<std::wstring> blacklisted_dlls_;
static HDESK alternate_desktop_handle_;
static HWINSTA alternate_winstation_handle_;
DISALLOW_COPY_AND_ASSIGN(PolicyBase);
};
+7 -1
Ver Arquivo
@@ -1,4 +1,4 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -31,6 +31,12 @@ enum ResultCode {
SBOX_ERROR_WAIT_ALREADY_CALLED = 9,
// A channel error prevented DoCall from executing.
SBOX_ERROR_CHANNEL_ERROR = 10,
// Failed to create the alternate desktop.
SBOX_ERROR_CANNOT_CREATE_DESKTOP = 11,
// Failed to create the alternate window station.
SBOX_ERROR_CANNOT_CREATE_WINSTATION = 12,
// Failed to switch back to the interactive window station.
SBOX_ERROR_FAILED_TO_SWITCH_BACK_WINSTATION = 13,
// Placeholder for last item of the enum.
SBOX_ERROR_LAST
};
+2 -8
Ver Arquivo
@@ -1,4 +1,4 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -83,7 +83,6 @@ TargetProcess::TargetProcess(HANDLE initial_token, HANDLE lockdown_token,
exe_name_(NULL),
sandbox_process_(NULL),
sandbox_thread_(NULL),
desktop_handle_(NULL),
sandbox_process_id_(0) {
}
@@ -113,8 +112,6 @@ TargetProcess::~TargetProcess() {
::CloseHandle(sandbox_process_);
if (shared_section_)
::CloseHandle(shared_section_);
if (desktop_handle_)
::CloseDesktop(desktop_handle_);
free(exe_name_);
}
@@ -130,15 +127,12 @@ DWORD TargetProcess::Create(const wchar_t* exe_path,
scoped_ptr_malloc<wchar_t> cmd_line(_wcsdup(command_line));
scoped_ptr_malloc<wchar_t> desktop_name(desktop ? _wcsdup(desktop) : NULL);
// Start the target process suspended.
const DWORD flags = CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB |
CREATE_UNICODE_ENVIRONMENT | DETACHED_PROCESS;
// Start the target process suspended
STARTUPINFO startup_info = {sizeof(STARTUPINFO)};
if (desktop) {
// Ensure that the desktop exists
desktop_handle_ = ::CreateDesktop(desktop_name.get(), NULL, NULL, 0,
DESKTOP_CREATEWINDOW, NULL);
startup_info.lpDesktop = desktop_name.get();
}
+1 -3
Ver Arquivo
@@ -1,4 +1,4 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -105,8 +105,6 @@ class TargetProcess {
void* base_address_;
// Full name of the target executable.
wchar_t* exe_name_;
// Desktop where the target process is running.
HDESK desktop_handle_;
// Function used for testing.
friend TargetProcess* MakeTestTargetProcess(HANDLE process,
+142
Ver Arquivo
@@ -0,0 +1,142 @@
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sandbox/src/window.h"
#include <aclapi.h>
#include "base/logging.h"
#include "base/scoped_ptr.h"
namespace {
// Gets the security attributes of a window object referenced by |handle|. The
// lpSecurityDescriptor member of the SECURITY_ATTRIBUTES parameter returned
// must be freed using LocalFree by the caller.
bool GetSecurityAttributes(HANDLE handle, SECURITY_ATTRIBUTES* attributes) {
attributes->bInheritHandle = FALSE;
attributes->nLength = sizeof(SECURITY_ATTRIBUTES);
PACL dacl = NULL;
DWORD result = ::GetSecurityInfo(handle, SE_WINDOW_OBJECT,
DACL_SECURITY_INFORMATION, NULL, NULL, &dacl,
NULL, &attributes->lpSecurityDescriptor);
if (ERROR_SUCCESS == result)
return true;
return false;
}
}
namespace sandbox {
ResultCode CreateAltWindowStation(HWINSTA* winsta) {
// Get the security attributes from the current window station; we will
// use this as the base security attributes for the new window station.
SECURITY_ATTRIBUTES attributes = {0};
if (!GetSecurityAttributes(::GetProcessWindowStation(), &attributes)) {
return SBOX_ERROR_CANNOT_CREATE_WINSTATION;
}
// Create the window station using NULL for the name to ask the os to
// generate it.
// TODO(nsylvain): don't ask for WINSTA_ALL_ACCESS if we don't need to.
*winsta = ::CreateWindowStationW(NULL, 0, WINSTA_ALL_ACCESS, &attributes);
LocalFree(attributes.lpSecurityDescriptor);
if (*winsta)
return SBOX_ALL_OK;
return SBOX_ERROR_CANNOT_CREATE_WINSTATION;
}
ResultCode CreateAltDesktop(HWINSTA winsta, HDESK* desktop) {
std::wstring desktop_name = L"sbox_alternate_desktop_";
// Append the current PID to the desktop name.
wchar_t buffer[16];
_snwprintf_s(buffer, sizeof(buffer) / sizeof(wchar_t), L"0x%X",
::GetCurrentProcessId());
desktop_name += buffer;
// Get the security attributes from the current desktop, we will use this as
// the base security attributes for the new desktop.
SECURITY_ATTRIBUTES attributes = {0};
if (!GetSecurityAttributes(GetThreadDesktop(GetCurrentThreadId()),
&attributes)) {
return SBOX_ERROR_CANNOT_CREATE_DESKTOP;
}
// Back up the current window station, in case we need to switch it.
HWINSTA current_winsta = ::GetProcessWindowStation();
if (winsta) {
// We need to switch to the alternate window station before creating the
// desktop.
if (!::SetProcessWindowStation(winsta)) {
::LocalFree(attributes.lpSecurityDescriptor);
return SBOX_ERROR_CANNOT_CREATE_DESKTOP;
}
}
// Create the destkop.
// TODO(nsylvain): don't ask for GENERIC_ALL if we don't need to.
*desktop = ::CreateDesktop(desktop_name.c_str(), NULL, NULL, 0, GENERIC_ALL,
&attributes);
::LocalFree(attributes.lpSecurityDescriptor);
if (winsta) {
// Revert to the right window station.
if (!::SetProcessWindowStation(current_winsta)) {
return SBOX_ERROR_FAILED_TO_SWITCH_BACK_WINSTATION;
}
}
if (*desktop)
return SBOX_ALL_OK;
return SBOX_ERROR_CANNOT_CREATE_DESKTOP;
}
std::wstring GetWindowObjectName(HANDLE handle) {
// Get the size of the name.
DWORD size = 0;
::GetUserObjectInformation(handle, UOI_NAME, NULL, 0, &size);
if (!size) {
NOTREACHED();
return std::wstring();
}
// Create the buffer that will hold the name.
scoped_ptr<wchar_t> name_buffer(new wchar_t[size]);
// Query the name of the object.
if (!::GetUserObjectInformation(handle, UOI_NAME, name_buffer.get(), size,
&size)) {
NOTREACHED();
return std::wstring();
}
return std::wstring(name_buffer.get());
}
std::wstring GetFullDesktopName(HWINSTA winsta, HDESK desktop) {
if (!desktop) {
NOTREACHED();
return std::wstring();
}
std::wstring name;
if (winsta) {
name = GetWindowObjectName(winsta);
name += L'\\';
}
name += GetWindowObjectName(desktop);
return name;
}
} // namespace sandbox
+39
Ver Arquivo
@@ -0,0 +1,39 @@
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SANDBOX_SRC_WINDOW_H_
#define SANDBOX_SRC_WINDOW_H_
#include <windows.h>
#include <string>
#include "sandbox/src/sandbox_types.h"
namespace sandbox {
// Creates a window station. The name is generated by the OS. The security
// descriptor is based on the security descriptor of the current window
// station.
ResultCode CreateAltWindowStation(HWINSTA* winsta);
// Creates a desktop. The name is a static string followed by the pid of the
// current process. The security descriptor on the new desktop is based on the
// security descriptor of the desktop associated with the current thread.
// If a winsta is specified, the function will switch to it before creating
// the desktop. If the functions fails the switch back to the current winsta,
// the function will return SBOX_ERROR_FAILED_TO_SWITCH_BACK_WINSTATION.
ResultCode CreateAltDesktop(HWINSTA winsta, HDESK* desktop);
// Returns the name of a desktop or a window station.
std::wstring GetWindowObjectName(HANDLE handle);
// Returns the name of the desktop referenced by |desktop|. If a window
// station is specified, the name is prepended with the window station name,
// followed by a backslash. This name can be used as the lpDesktop parameter
// to CreateProcess.
std::wstring GetFullDesktopName(HWINSTA winsta, HDESK desktop);
} // namespace sandbox
#endif // SANDBOX_SRC_WINDOW_H_
+2 -2
Ver Arquivo
@@ -1,4 +1,4 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -77,7 +77,7 @@ TEST(ValidationSuite, TestRegistry) {
// to get to the interactive desktop or to make the sbox desktop interactive.
TEST(ValidationSuite, TestDesktop) {
TestRunner runner;
runner.GetPolicy()->SetDesktop(L"sbox_validation_desktop");
runner.GetPolicy()->SetAlternateDesktop(false);
EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenInteractiveDesktop NULL"));
EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"SwitchToSboxDesktop NULL"));
}