Commit b6a4ff86 authored by jbauman's avatar jbauman Committed by Commit bot

Fix sandbox::PolicyBase leak

StartSandboxedProcess was missing a Release call, so this was always
leaking. Use scoped_refptr instead to fix that and prevent it from
happening in the future.
TBR=piman@chromium.org
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.win:win10_chromium_x64_rel_ng

Review-Url: https://codereview.chromium.org/2316333003
Cr-Commit-Position: refs/heads/master@{#417313}
parent b307c270
...@@ -27,10 +27,10 @@ bool InitializeSandbox(sandbox::SandboxInterfaceInfo* sandbox_info) { ...@@ -27,10 +27,10 @@ bool InitializeSandbox(sandbox::SandboxInterfaceInfo* sandbox_info) {
// broken. This has to run before threads and windows are created. // broken. This has to run before threads and windows are created.
if (!command_line.HasSwitch(switches::kNoSandbox)) { if (!command_line.HasSwitch(switches::kNoSandbox)) {
// Precreate the desktop and window station used by the renderers. // Precreate the desktop and window station used by the renderers.
sandbox::TargetPolicy* policy = broker_services->CreatePolicy(); scoped_refptr<sandbox::TargetPolicy> policy =
broker_services->CreatePolicy();
sandbox::ResultCode result = policy->CreateAlternateDesktop(true); sandbox::ResultCode result = policy->CreateAlternateDesktop(true);
CHECK(sandbox::SBOX_ERROR_FAILED_TO_SWITCH_BACK_WINSTATION != result); CHECK(sandbox::SBOX_ERROR_FAILED_TO_SWITCH_BACK_WINSTATION != result);
policy->Release();
} }
return true; return true;
} }
......
...@@ -708,7 +708,8 @@ sandbox::ResultCode StartSandboxedProcess( ...@@ -708,7 +708,8 @@ sandbox::ResultCode StartSandboxedProcess(
return sandbox::SBOX_ALL_OK; return sandbox::SBOX_ALL_OK;
} }
sandbox::TargetPolicy* policy = g_broker_services->CreatePolicy(); scoped_refptr<sandbox::TargetPolicy> policy =
g_broker_services->CreatePolicy();
// Add any handles to be inherited to the policy. // Add any handles to be inherited to the policy.
for (HANDLE handle : handles_to_inherit) for (HANDLE handle : handles_to_inherit)
...@@ -737,7 +738,7 @@ sandbox::ResultCode StartSandboxedProcess( ...@@ -737,7 +738,7 @@ sandbox::ResultCode StartSandboxedProcess(
#if !defined(NACL_WIN64) #if !defined(NACL_WIN64)
if (type_str == switches::kRendererProcess && if (type_str == switches::kRendererProcess &&
IsWin32kRendererLockdownEnabled()) { IsWin32kRendererLockdownEnabled()) {
result = AddWin32kLockdownPolicy(policy, false); result = AddWin32kLockdownPolicy(policy.get(), false);
if (result != sandbox::SBOX_ALL_OK) if (result != sandbox::SBOX_ALL_OK)
return result; return result;
} }
...@@ -751,12 +752,12 @@ sandbox::ResultCode StartSandboxedProcess( ...@@ -751,12 +752,12 @@ sandbox::ResultCode StartSandboxedProcess(
if (result != sandbox::SBOX_ALL_OK) if (result != sandbox::SBOX_ALL_OK)
return result; return result;
result = SetJobLevel(*cmd_line, sandbox::JOB_LOCKDOWN, 0, policy); result = SetJobLevel(*cmd_line, sandbox::JOB_LOCKDOWN, 0, policy.get());
if (result != sandbox::SBOX_ALL_OK) if (result != sandbox::SBOX_ALL_OK)
return result; return result;
if (!delegate->DisableDefaultPolicy()) { if (!delegate->DisableDefaultPolicy()) {
result = AddPolicyForSandboxedProcess(policy); result = AddPolicyForSandboxedProcess(policy.get());
if (result != sandbox::SBOX_ALL_OK) if (result != sandbox::SBOX_ALL_OK)
return result; return result;
} }
...@@ -765,7 +766,7 @@ sandbox::ResultCode StartSandboxedProcess( ...@@ -765,7 +766,7 @@ sandbox::ResultCode StartSandboxedProcess(
if (type_str == switches::kRendererProcess || if (type_str == switches::kRendererProcess ||
type_str == switches::kPpapiPluginProcess) { type_str == switches::kPpapiPluginProcess) {
AddDirectory(base::DIR_WINDOWS_FONTS, NULL, true, AddDirectory(base::DIR_WINDOWS_FONTS, NULL, true,
sandbox::TargetPolicy::FILES_ALLOW_READONLY, policy); sandbox::TargetPolicy::FILES_ALLOW_READONLY, policy.get());
} }
#endif #endif
...@@ -776,7 +777,7 @@ sandbox::ResultCode StartSandboxedProcess( ...@@ -776,7 +777,7 @@ sandbox::ResultCode StartSandboxedProcess(
cmd_line->AppendSwitchASCII("ignored", " --type=renderer "); cmd_line->AppendSwitchASCII("ignored", " --type=renderer ");
} }
result = AddGenericPolicy(policy); result = AddGenericPolicy(policy.get());
if (result != sandbox::SBOX_ALL_OK) { if (result != sandbox::SBOX_ALL_OK) {
NOTREACHED(); NOTREACHED();
...@@ -801,7 +802,7 @@ sandbox::ResultCode StartSandboxedProcess( ...@@ -801,7 +802,7 @@ sandbox::ResultCode StartSandboxedProcess(
policy->SetStdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE)); policy->SetStdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE));
policy->SetStderrHandle(GetStdHandle(STD_ERROR_HANDLE)); policy->SetStderrHandle(GetStdHandle(STD_ERROR_HANDLE));
if (!delegate->PreSpawnTarget(policy)) if (!delegate->PreSpawnTarget(policy.get()))
return sandbox::SBOX_ERROR_DELEGATE_PRE_SPAWN; return sandbox::SBOX_ERROR_DELEGATE_PRE_SPAWN;
TRACE_EVENT_BEGIN0("startup", "StartProcessWithAccess::LAUNCHPROCESS"); TRACE_EVENT_BEGIN0("startup", "StartProcessWithAccess::LAUNCHPROCESS");
......
...@@ -500,7 +500,7 @@ bool MainUIWindow::SpawnTarget() { ...@@ -500,7 +500,7 @@ bool MainUIWindow::SpawnTarget() {
arguments[size_call - 1] = L'\0'; arguments[size_call - 1] = L'\0';
sandbox::TargetPolicy* policy = broker_->CreatePolicy(); scoped_refptr<sandbox::TargetPolicy> policy = broker_->CreatePolicy();
policy->SetJobLevel(sandbox::JOB_LOCKDOWN, 0); policy->SetJobLevel(sandbox::JOB_LOCKDOWN, 0);
policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS, policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
sandbox::USER_LOCKDOWN); sandbox::USER_LOCKDOWN);
...@@ -519,7 +519,6 @@ bool MainUIWindow::SpawnTarget() { ...@@ -519,7 +519,6 @@ bool MainUIWindow::SpawnTarget() {
broker_->SpawnTarget(spawn_target_.c_str(), arguments, policy, broker_->SpawnTarget(spawn_target_.c_str(), arguments, policy,
&warning_result, &last_error, &target_); &warning_result, &last_error, &target_);
policy->Release();
policy = NULL; policy = NULL;
bool return_value = false; bool return_value = false;
......
...@@ -54,7 +54,8 @@ enum { ...@@ -54,7 +54,8 @@ enum {
// Helper structure that allows the Broker to associate a job notification // Helper structure that allows the Broker to associate a job notification
// with a job object and with a policy. // with a job object and with a policy.
struct JobTracker { struct JobTracker {
JobTracker(base::win::ScopedHandle job, sandbox::PolicyBase* policy) JobTracker(base::win::ScopedHandle job,
scoped_refptr<sandbox::PolicyBase> policy)
: job(std::move(job)), policy(policy) {} : job(std::move(job)), policy(policy) {}
~JobTracker() { ~JobTracker() {
FreeResources(); FreeResources();
...@@ -65,7 +66,7 @@ struct JobTracker { ...@@ -65,7 +66,7 @@ struct JobTracker {
void FreeResources(); void FreeResources();
base::win::ScopedHandle job; base::win::ScopedHandle job;
sandbox::PolicyBase* policy; scoped_refptr<sandbox::PolicyBase> policy;
}; };
void JobTracker::FreeResources() { void JobTracker::FreeResources() {
...@@ -79,8 +80,7 @@ void JobTracker::FreeResources() { ...@@ -79,8 +80,7 @@ void JobTracker::FreeResources() {
// In OnJobEmpty() we don't actually use the job handle directly. // In OnJobEmpty() we don't actually use the job handle directly.
policy->OnJobEmpty(stale_job_handle); policy->OnJobEmpty(stale_job_handle);
policy->Release(); policy = nullptr;
policy = NULL;
} }
} }
...@@ -142,10 +142,13 @@ BrokerServicesBase::~BrokerServicesBase() { ...@@ -142,10 +142,13 @@ BrokerServicesBase::~BrokerServicesBase() {
::DeleteCriticalSection(&lock_); ::DeleteCriticalSection(&lock_);
} }
TargetPolicy* BrokerServicesBase::CreatePolicy() { scoped_refptr<TargetPolicy> BrokerServicesBase::CreatePolicy() {
// If you change the type of the object being created here you must also // If you change the type of the object being created here you must also
// change the downcast to it in SpawnTarget(). // change the downcast to it in SpawnTarget().
return new PolicyBase; scoped_refptr<TargetPolicy> policy(new PolicyBase);
// PolicyBase starts with refcount 1.
policy->Release();
return policy;
} }
// The worker thread stays in a loop waiting for asynchronous notifications // The worker thread stays in a loop waiting for asynchronous notifications
...@@ -268,7 +271,7 @@ DWORD WINAPI BrokerServicesBase::TargetEventsThread(PVOID param) { ...@@ -268,7 +271,7 @@ DWORD WINAPI BrokerServicesBase::TargetEventsThread(PVOID param) {
// process inside the sandbox. // process inside the sandbox.
ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path, ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path,
const wchar_t* command_line, const wchar_t* command_line,
TargetPolicy* policy, scoped_refptr<TargetPolicy> policy,
ResultCode* last_warning, ResultCode* last_warning,
DWORD* last_error, DWORD* last_error,
PROCESS_INFORMATION* target_info) { PROCESS_INFORMATION* target_info) {
...@@ -289,7 +292,7 @@ ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path, ...@@ -289,7 +292,7 @@ ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path,
AutoLock lock(&lock_); AutoLock lock(&lock_);
// This downcast is safe as long as we control CreatePolicy() // This downcast is safe as long as we control CreatePolicy()
PolicyBase* policy_base = static_cast<PolicyBase*>(policy); scoped_refptr<PolicyBase> policy_base(static_cast<PolicyBase*>(policy.get()));
// Construct the tokens and the job object that we are going to associate // Construct the tokens and the job object that we are going to associate
// with the soon to be created target process. // with the soon to be created target process.
...@@ -441,7 +444,6 @@ ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path, ...@@ -441,7 +444,6 @@ ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path,
// We are going to keep a pointer to the policy because we'll call it when // We are going to keep a pointer to the policy because we'll call it when
// the job object generates notifications using the completion port. // the job object generates notifications using the completion port.
policy_base->AddRef();
if (job.IsValid()) { if (job.IsValid()) {
std::unique_ptr<JobTracker> tracker( std::unique_ptr<JobTracker> tracker(
new JobTracker(std::move(job), policy_base)); new JobTracker(std::move(job), policy_base));
......
...@@ -45,10 +45,10 @@ class BrokerServicesBase final : public BrokerServices, ...@@ -45,10 +45,10 @@ class BrokerServicesBase final : public BrokerServices,
// BrokerServices interface. // BrokerServices interface.
ResultCode Init() override; ResultCode Init() override;
TargetPolicy* CreatePolicy() override; scoped_refptr<TargetPolicy> CreatePolicy() override;
ResultCode SpawnTarget(const wchar_t* exe_path, ResultCode SpawnTarget(const wchar_t* exe_path,
const wchar_t* command_line, const wchar_t* command_line,
TargetPolicy* policy, scoped_refptr<TargetPolicy> policy,
ResultCode* last_warning, ResultCode* last_warning,
DWORD* last_error, DWORD* last_error,
PROCESS_INFORMATION* target) override; PROCESS_INFORMATION* target) override;
......
...@@ -222,9 +222,9 @@ TEST(PolicyTargetTest, DesktopPolicy) { ...@@ -222,9 +222,9 @@ TEST(PolicyTargetTest, DesktopPolicy) {
BrokerServices* broker = GetBroker(); BrokerServices* broker = GetBroker();
// Precreate the desktop. // Precreate the desktop.
TargetPolicy* temp_policy = broker->CreatePolicy(); scoped_refptr<TargetPolicy> temp_policy = broker->CreatePolicy();
temp_policy->CreateAlternateDesktop(false); temp_policy->CreateAlternateDesktop(false);
temp_policy->Release(); temp_policy = nullptr;
ASSERT_TRUE(broker != NULL); ASSERT_TRUE(broker != NULL);
...@@ -242,7 +242,7 @@ TEST(PolicyTargetTest, DesktopPolicy) { ...@@ -242,7 +242,7 @@ TEST(PolicyTargetTest, DesktopPolicy) {
DWORD last_error = ERROR_SUCCESS; DWORD last_error = ERROR_SUCCESS;
base::win::ScopedProcessInformation target; base::win::ScopedProcessInformation target;
TargetPolicy* policy = broker->CreatePolicy(); scoped_refptr<TargetPolicy> policy = broker->CreatePolicy();
policy->SetAlternateDesktop(false); policy->SetAlternateDesktop(false);
policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN); policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN);
PROCESS_INFORMATION temp_process_info = {}; PROCESS_INFORMATION temp_process_info = {};
...@@ -250,7 +250,7 @@ TEST(PolicyTargetTest, DesktopPolicy) { ...@@ -250,7 +250,7 @@ TEST(PolicyTargetTest, DesktopPolicy) {
broker->SpawnTarget(prog_name, arguments.c_str(), policy, &warning_result, broker->SpawnTarget(prog_name, arguments.c_str(), policy, &warning_result,
&last_error, &temp_process_info); &last_error, &temp_process_info);
base::string16 desktop_name = policy->GetAlternateDesktop(); base::string16 desktop_name = policy->GetAlternateDesktop();
policy->Release(); policy = nullptr;
EXPECT_EQ(SBOX_ALL_OK, result); EXPECT_EQ(SBOX_ALL_OK, result);
if (result == SBOX_ALL_OK) if (result == SBOX_ALL_OK)
...@@ -274,7 +274,7 @@ TEST(PolicyTargetTest, DesktopPolicy) { ...@@ -274,7 +274,7 @@ TEST(PolicyTargetTest, DesktopPolicy) {
// Close the desktop handle. // Close the desktop handle.
temp_policy = broker->CreatePolicy(); temp_policy = broker->CreatePolicy();
temp_policy->DestroyAlternateDesktop(); temp_policy->DestroyAlternateDesktop();
temp_policy->Release(); temp_policy = nullptr;
// Make sure the desktop does not exist anymore. // Make sure the desktop does not exist anymore.
desk = ::OpenDesktop(desktop_name.c_str(), 0, FALSE, DESKTOP_ENUMERATE); desk = ::OpenDesktop(desktop_name.c_str(), 0, FALSE, DESKTOP_ENUMERATE);
...@@ -289,9 +289,9 @@ TEST(PolicyTargetTest, WinstaPolicy) { ...@@ -289,9 +289,9 @@ TEST(PolicyTargetTest, WinstaPolicy) {
BrokerServices* broker = GetBroker(); BrokerServices* broker = GetBroker();
// Precreate the desktop. // Precreate the desktop.
TargetPolicy* temp_policy = broker->CreatePolicy(); scoped_refptr<TargetPolicy> temp_policy = broker->CreatePolicy();
temp_policy->CreateAlternateDesktop(true); temp_policy->CreateAlternateDesktop(true);
temp_policy->Release(); temp_policy = nullptr;
ASSERT_TRUE(broker != NULL); ASSERT_TRUE(broker != NULL);
...@@ -308,7 +308,7 @@ TEST(PolicyTargetTest, WinstaPolicy) { ...@@ -308,7 +308,7 @@ TEST(PolicyTargetTest, WinstaPolicy) {
ResultCode warning_result = SBOX_ALL_OK; ResultCode warning_result = SBOX_ALL_OK;
base::win::ScopedProcessInformation target; base::win::ScopedProcessInformation target;
TargetPolicy* policy = broker->CreatePolicy(); scoped_refptr<TargetPolicy> policy = broker->CreatePolicy();
policy->SetAlternateDesktop(true); policy->SetAlternateDesktop(true);
policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN); policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN);
PROCESS_INFORMATION temp_process_info = {}; PROCESS_INFORMATION temp_process_info = {};
...@@ -317,7 +317,7 @@ TEST(PolicyTargetTest, WinstaPolicy) { ...@@ -317,7 +317,7 @@ TEST(PolicyTargetTest, WinstaPolicy) {
broker->SpawnTarget(prog_name, arguments.c_str(), policy, &warning_result, broker->SpawnTarget(prog_name, arguments.c_str(), policy, &warning_result,
&last_error, &temp_process_info); &last_error, &temp_process_info);
base::string16 desktop_name = policy->GetAlternateDesktop(); base::string16 desktop_name = policy->GetAlternateDesktop();
policy->Release(); policy = nullptr;
EXPECT_EQ(SBOX_ALL_OK, result); EXPECT_EQ(SBOX_ALL_OK, result);
if (result == SBOX_ALL_OK) if (result == SBOX_ALL_OK)
...@@ -349,7 +349,7 @@ TEST(PolicyTargetTest, WinstaPolicy) { ...@@ -349,7 +349,7 @@ TEST(PolicyTargetTest, WinstaPolicy) {
// Close the desktop handle. // Close the desktop handle.
temp_policy = broker->CreatePolicy(); temp_policy = broker->CreatePolicy();
temp_policy->DestroyAlternateDesktop(); temp_policy->DestroyAlternateDesktop();
temp_policy->Release(); temp_policy = nullptr;
} }
// Launches the app in the sandbox and share a handle with it. The app should // Launches the app in the sandbox and share a handle with it. The app should
...@@ -377,7 +377,7 @@ TEST(PolicyTargetTest, ShareHandleTest) { ...@@ -377,7 +377,7 @@ TEST(PolicyTargetTest, ShareHandleTest) {
wchar_t prog_name[MAX_PATH]; wchar_t prog_name[MAX_PATH];
GetModuleFileNameW(NULL, prog_name, MAX_PATH); GetModuleFileNameW(NULL, prog_name, MAX_PATH);
TargetPolicy* policy = broker->CreatePolicy(); scoped_refptr<TargetPolicy> policy = broker->CreatePolicy();
policy->AddHandleToShare(read_only_view.handle().GetHandle()); policy->AddHandleToShare(read_only_view.handle().GetHandle());
base::string16 arguments(L"\""); base::string16 arguments(L"\"");
...@@ -397,7 +397,7 @@ TEST(PolicyTargetTest, ShareHandleTest) { ...@@ -397,7 +397,7 @@ TEST(PolicyTargetTest, ShareHandleTest) {
result = result =
broker->SpawnTarget(prog_name, arguments.c_str(), policy, &warning_result, broker->SpawnTarget(prog_name, arguments.c_str(), policy, &warning_result,
&last_error, &temp_process_info); &last_error, &temp_process_info);
policy->Release(); policy = nullptr;
EXPECT_EQ(SBOX_ALL_OK, result); EXPECT_EQ(SBOX_ALL_OK, result);
if (result == SBOX_ALL_OK) if (result == SBOX_ALL_OK)
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <windows.h> #include <windows.h>
#include "base/memory/ref_counted.h"
#include "sandbox/win/src/sandbox_policy.h" #include "sandbox/win/src/sandbox_policy.h"
#include "sandbox/win/src/sandbox_types.h" #include "sandbox/win/src/sandbox_types.h"
...@@ -56,7 +57,7 @@ class BrokerServices { ...@@ -56,7 +57,7 @@ class BrokerServices {
// Returns the interface pointer to a new, empty policy object. Use this // Returns the interface pointer to a new, empty policy object. Use this
// interface to specify the sandbox policy for new processes created by // interface to specify the sandbox policy for new processes created by
// SpawnTarget() // SpawnTarget()
virtual TargetPolicy* CreatePolicy() = 0; virtual scoped_refptr<TargetPolicy> CreatePolicy() = 0;
// Creates a new target (child process) in a suspended state. // Creates a new target (child process) in a suspended state.
// Parameters: // Parameters:
...@@ -79,7 +80,7 @@ class BrokerServices { ...@@ -79,7 +80,7 @@ class BrokerServices {
// ALL_OK if successful. All other return values imply failure. // ALL_OK if successful. All other return values imply failure.
virtual ResultCode SpawnTarget(const wchar_t* exe_path, virtual ResultCode SpawnTarget(const wchar_t* exe_path,
const wchar_t* command_line, const wchar_t* command_line,
TargetPolicy* policy, scoped_refptr<TargetPolicy> policy,
ResultCode* last_warning, ResultCode* last_warning,
DWORD* last_error, DWORD* last_error,
PROCESS_INFORMATION* target) = 0; PROCESS_INFORMATION* target) = 0;
......
...@@ -136,15 +136,12 @@ void TestRunner::Init(JobLevel job_level, ...@@ -136,15 +136,12 @@ void TestRunner::Init(JobLevel job_level,
} }
TargetPolicy* TestRunner::GetPolicy() { TargetPolicy* TestRunner::GetPolicy() {
return policy_; return policy_.get();
} }
TestRunner::~TestRunner() { TestRunner::~TestRunner() {
if (target_process_.IsValid() && kill_on_destruction_) if (target_process_.IsValid() && kill_on_destruction_)
::TerminateProcess(target_process_.Get(), 0); ::TerminateProcess(target_process_.Get(), 0);
if (policy_)
policy_->Release();
} }
bool TestRunner::AddRule(TargetPolicy::SubSystem subsystem, bool TestRunner::AddRule(TargetPolicy::SubSystem subsystem,
......
...@@ -139,7 +139,7 @@ class TestRunner { ...@@ -139,7 +139,7 @@ class TestRunner {
int InternalRunTest(const wchar_t* command); int InternalRunTest(const wchar_t* command);
BrokerServices* broker_; BrokerServices* broker_;
TargetPolicy* policy_; scoped_refptr<TargetPolicy> policy_;
DWORD timeout_; DWORD timeout_;
SboxTestsState state_; SboxTestsState state_;
bool is_init_; bool is_init_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment