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:
@@ -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
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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,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() {
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -183,6 +183,14 @@
|
||||
RelativePath=".\sid.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\window.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\window.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Interception"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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,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,
|
||||
|
||||
@@ -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
|
||||
@@ -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_
|
||||
@@ -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"));
|
||||
}
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário