123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596 |
- // Copyright (c) 2012 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 "base/memory/read_only_shared_memory_region.h"
- #include "base/memory/writable_shared_memory_region.h"
- #include "base/strings/string_number_conversions.h"
- #include "base/strings/string_piece.h"
- #include "base/strings/string_util.h"
- #include "base/win/scoped_process_information.h"
- #include "base/win/windows_version.h"
- #include "build/build_config.h"
- #include "sandbox/win/src/broker_services.h"
- #include "sandbox/win/src/sandbox.h"
- #include "sandbox/win/src/sandbox_factory.h"
- #include "sandbox/win/src/sandbox_policy.h"
- #include "sandbox/win/src/sandbox_utils.h"
- #include "sandbox/win/src/target_services.h"
- #include "sandbox/win/tests/common/controller.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #if BUILDFLAG(IS_WIN)
- #include "base/win/win_util.h"
- #endif
- namespace sandbox {
- #define BINDNTDLL(name) \
- name##Function name = reinterpret_cast<name##Function>( \
- ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), #name))
- // Reverts to self and verify that SetInformationToken was faked. Returns
- // SBOX_TEST_SUCCEEDED if faked and SBOX_TEST_FAILED if not faked.
- SBOX_TESTS_COMMAND int PolicyTargetTest_token(int argc, wchar_t** argv) {
- HANDLE thread_token;
- // Get the thread token, using impersonation.
- if (!::OpenThreadToken(GetCurrentThread(),
- TOKEN_IMPERSONATE | TOKEN_DUPLICATE, false,
- &thread_token))
- return ::GetLastError();
- ::RevertToSelf();
- ::CloseHandle(thread_token);
- int ret = SBOX_TEST_FAILED;
- if (::OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_DUPLICATE,
- false, &thread_token)) {
- ret = SBOX_TEST_SUCCEEDED;
- ::CloseHandle(thread_token);
- }
- return ret;
- }
- // Stores the high privilege token on a static variable, change impersonation
- // again to that one and verify that we are not interfering anymore with
- // RevertToSelf.
- SBOX_TESTS_COMMAND int PolicyTargetTest_steal(int argc, wchar_t** argv) {
- static HANDLE thread_token;
- if (!SandboxFactory::GetTargetServices()->GetState()->RevertedToSelf()) {
- if (!::OpenThreadToken(GetCurrentThread(),
- TOKEN_IMPERSONATE | TOKEN_DUPLICATE, false,
- &thread_token))
- return ::GetLastError();
- } else {
- if (!::SetThreadToken(nullptr, thread_token))
- return ::GetLastError();
- // See if we fake the call again.
- int ret = PolicyTargetTest_token(argc, argv);
- ::CloseHandle(thread_token);
- return ret;
- }
- return 0;
- }
- // Opens the thread token with and without impersonation.
- SBOX_TESTS_COMMAND int PolicyTargetTest_token2(int argc, wchar_t** argv) {
- HANDLE thread_token;
- // Get the thread token, using impersonation.
- if (!::OpenThreadToken(GetCurrentThread(),
- TOKEN_IMPERSONATE | TOKEN_DUPLICATE, false,
- &thread_token))
- return ::GetLastError();
- ::CloseHandle(thread_token);
- // Get the thread token, without impersonation.
- if (!OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_DUPLICATE,
- true, &thread_token))
- return ::GetLastError();
- ::CloseHandle(thread_token);
- return SBOX_TEST_SUCCEEDED;
- }
- // Opens the thread token with and without impersonation, using
- // NtOpenThreadTokenEX.
- SBOX_TESTS_COMMAND int PolicyTargetTest_token3(int argc, wchar_t** argv) {
- BINDNTDLL(NtOpenThreadTokenEx);
- if (!NtOpenThreadTokenEx)
- return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
- HANDLE thread_token;
- // Get the thread token, using impersonation.
- NTSTATUS status = NtOpenThreadTokenEx(GetCurrentThread(),
- TOKEN_IMPERSONATE | TOKEN_DUPLICATE,
- false, 0, &thread_token);
- if (status == STATUS_NO_TOKEN)
- return ERROR_NO_TOKEN;
- if (!NT_SUCCESS(status))
- return SBOX_TEST_FAILED;
- ::CloseHandle(thread_token);
- // Get the thread token, without impersonation.
- status = NtOpenThreadTokenEx(GetCurrentThread(),
- TOKEN_IMPERSONATE | TOKEN_DUPLICATE, true, 0,
- &thread_token);
- if (!NT_SUCCESS(status))
- return SBOX_TEST_FAILED;
- ::CloseHandle(thread_token);
- return SBOX_TEST_SUCCEEDED;
- }
- // Tests that we can open the current thread.
- SBOX_TESTS_COMMAND int PolicyTargetTest_thread(int argc, wchar_t** argv) {
- DWORD thread_id = ::GetCurrentThreadId();
- HANDLE thread = ::OpenThread(SYNCHRONIZE, false, thread_id);
- if (!thread)
- return ::GetLastError();
- if (!::CloseHandle(thread))
- return ::GetLastError();
- return SBOX_TEST_SUCCEEDED;
- }
- // New thread entry point: do nothing.
- DWORD WINAPI PolicyTargetTest_thread_main(void* param) {
- ::Sleep(INFINITE);
- return 0;
- }
- // Tests that we can create a new thread, and open it.
- SBOX_TESTS_COMMAND int PolicyTargetTest_thread2(int argc, wchar_t** argv) {
- // Use default values to create a new thread.
- DWORD thread_id;
- HANDLE thread = ::CreateThread(nullptr, 0, &PolicyTargetTest_thread_main, 0,
- 0, &thread_id);
- if (!thread)
- return ::GetLastError();
- if (!::CloseHandle(thread))
- return ::GetLastError();
- thread = ::OpenThread(SYNCHRONIZE, false, thread_id);
- if (!thread)
- return ::GetLastError();
- if (!::CloseHandle(thread))
- return ::GetLastError();
- return SBOX_TEST_SUCCEEDED;
- }
- // Tests that we can call CreateProcess.
- SBOX_TESTS_COMMAND int PolicyTargetTest_process(int argc, wchar_t** argv) {
- // Use default values to create a new process.
- STARTUPINFO startup_info = {0};
- startup_info.cb = sizeof(startup_info);
- PROCESS_INFORMATION temp_process_info = {};
- // Note: CreateProcessW() can write to its lpCommandLine, don't pass a
- // raw string literal.
- std::wstring writable_cmdline_str(L"foo.exe");
- if (!::CreateProcessW(L"foo.exe", &writable_cmdline_str[0], nullptr, nullptr,
- false, 0, nullptr, nullptr, &startup_info,
- &temp_process_info))
- return SBOX_TEST_SUCCEEDED;
- base::win::ScopedProcessInformation process_info(temp_process_info);
- return SBOX_TEST_FAILED;
- }
- TEST(PolicyTargetTest, SetInformationThread) {
- TestRunner runner;
- runner.SetTestState(BEFORE_REVERT);
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token"));
- TestRunner runner1;
- runner1.SetTestState(AFTER_REVERT);
- EXPECT_EQ(ERROR_NO_TOKEN, runner1.RunTest(L"PolicyTargetTest_token"));
- TestRunner runner2;
- runner2.SetTestState(EVERY_STATE);
- EXPECT_EQ(SBOX_TEST_FAILED, runner2.RunTest(L"PolicyTargetTest_steal"));
- }
- TEST(PolicyTargetTest, OpenThreadToken) {
- TestRunner runner;
- runner.SetTestState(BEFORE_REVERT);
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token2"));
- TestRunner runner2;
- runner2.SetTestState(AFTER_REVERT);
- EXPECT_EQ(ERROR_NO_TOKEN, runner2.RunTest(L"PolicyTargetTest_token2"));
- }
- TEST(PolicyTargetTest, OpenThreadTokenEx) {
- TestRunner runner;
- runner.SetTestState(BEFORE_REVERT);
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token3"));
- TestRunner runner2;
- runner2.SetTestState(AFTER_REVERT);
- EXPECT_EQ(ERROR_NO_TOKEN, runner2.RunTest(L"PolicyTargetTest_token3"));
- }
- TEST(PolicyTargetTest, OpenThread) {
- TestRunner runner;
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_thread"))
- << "Opens the current thread";
- TestRunner runner2;
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner2.RunTest(L"PolicyTargetTest_thread2"))
- << "Creates a new thread and opens it";
- }
- TEST(PolicyTargetTest, OpenProcess) {
- TestRunner runner;
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_process"))
- << "Opens a process";
- }
- TEST(PolicyTargetTest, PolicyBaseNoJobLifetime) {
- TestRunner runner(JobLevel::kNone, USER_RESTRICTED_SAME_ACCESS,
- USER_LOCKDOWN);
- // TargetPolicy and its SharedMemIPCServer should continue to exist until
- // the child process dies.
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_thread"))
- << "Opens the current thread";
- }
- // Sets the desktop for the current thread to be one with a null DACL, then
- // launches a sandboxed app. Validates that the sandboxed app has access to the
- // desktop.
- TEST(PolicyTargetTest, InheritedDesktopPolicy) {
- // Create a desktop with a null dacl - which should allow access to
- // everything.
- SECURITY_ATTRIBUTES attributes = {};
- attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
- SECURITY_DESCRIPTOR security_desc = {};
- ::InitializeSecurityDescriptor(&security_desc, SECURITY_DESCRIPTOR_REVISION);
- ::SetSecurityDescriptorDacl(&security_desc, true, nullptr, false);
- attributes.lpSecurityDescriptor = &security_desc;
- HDESK null_dacl_desktop_handle = CreateDesktop(
- L"null_dacl_desktop", nullptr, nullptr, 0, GENERIC_ALL, &attributes);
- EXPECT_TRUE(null_dacl_desktop_handle);
- // Switch to the null dacl desktop and run the test.
- HDESK old_desktop = ::GetThreadDesktop(::GetCurrentThreadId());
- EXPECT_TRUE(null_dacl_desktop_handle);
- EXPECT_TRUE(::SetThreadDesktop(null_dacl_desktop_handle));
- BrokerServices* broker = GetBroker();
- // Precreate the desktop.
- broker->CreatePolicy()->CreateAlternateDesktop(false);
- ASSERT_TRUE(broker);
- // Get the path to the sandboxed app.
- wchar_t prog_name[MAX_PATH];
- GetModuleFileNameW(nullptr, 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;
- ResultCode warning_result = SBOX_ALL_OK;
- DWORD last_error = ERROR_SUCCESS;
- base::win::ScopedProcessInformation target;
- auto policy = broker->CreatePolicy();
- policy->SetAlternateDesktop(false);
- policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN);
- PROCESS_INFORMATION temp_process_info = {};
- result =
- broker->SpawnTarget(prog_name, arguments.c_str(), std::move(policy),
- &warning_result, &last_error, &temp_process_info);
- EXPECT_EQ(SBOX_ALL_OK, result);
- if (result == SBOX_ALL_OK)
- target.Set(temp_process_info);
- // Run the process for some time to make sure it doesn't crash on launch
- EXPECT_EQ(1u, ::ResumeThread(target.thread_handle()));
- EXPECT_EQ(static_cast<DWORD>(WAIT_TIMEOUT),
- ::WaitForSingleObject(target.process_handle(), 2000));
- EXPECT_TRUE(::TerminateProcess(target.process_handle(), 0));
- ::WaitForSingleObject(target.process_handle(), INFINITE);
- // Close the desktop handle.
- broker->CreatePolicy()->DestroyAlternateDesktop();
- // Close the null dacl desktop.
- EXPECT_TRUE(::SetThreadDesktop(old_desktop));
- EXPECT_TRUE(::CloseDesktop(null_dacl_desktop_handle));
- }
- // Launches the app in the sandbox and ask it to wait in an
- // infinite loop. Waits for 2 seconds and then check if the
- // desktop associated with the app thread is not the same as the
- // current desktop.
- TEST(PolicyTargetTest, DesktopPolicy) {
- BrokerServices* broker = GetBroker();
- // Precreate the desktop.
- broker->CreatePolicy()->CreateAlternateDesktop(false);
- ASSERT_TRUE(broker);
- // Get the path to the sandboxed app.
- wchar_t prog_name[MAX_PATH];
- GetModuleFileNameW(nullptr, 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;
- ResultCode warning_result = SBOX_ALL_OK;
- DWORD last_error = ERROR_SUCCESS;
- base::win::ScopedProcessInformation target;
- auto policy = broker->CreatePolicy();
- policy->SetAlternateDesktop(false);
- policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN);
- PROCESS_INFORMATION temp_process_info = {};
- // Keep the desktop name to test against later.
- std::wstring desktop_name = policy->GetAlternateDesktop();
- result =
- broker->SpawnTarget(prog_name, arguments.c_str(), std::move(policy),
- &warning_result, &last_error, &temp_process_info);
- EXPECT_EQ(SBOX_ALL_OK, result);
- if (result == SBOX_ALL_OK)
- target.Set(temp_process_info);
- EXPECT_EQ(1u, ::ResumeThread(target.thread_handle()));
- EXPECT_EQ(static_cast<DWORD>(WAIT_TIMEOUT),
- ::WaitForSingleObject(target.process_handle(), 2000));
- EXPECT_NE(::GetThreadDesktop(target.thread_id()),
- ::GetThreadDesktop(::GetCurrentThreadId()));
- HDESK desk = ::OpenDesktop(desktop_name.c_str(), 0, false, DESKTOP_ENUMERATE);
- EXPECT_TRUE(desk);
- EXPECT_TRUE(::CloseDesktop(desk));
- EXPECT_TRUE(::TerminateProcess(target.process_handle(), 0));
- ::WaitForSingleObject(target.process_handle(), INFINITE);
- // Close the desktop handle.
- broker->CreatePolicy()->DestroyAlternateDesktop();
- // Make sure the desktop does not exist anymore.
- desk = ::OpenDesktop(desktop_name.c_str(), 0, false, DESKTOP_ENUMERATE);
- EXPECT_FALSE(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.
- broker->CreatePolicy()->CreateAlternateDesktop(true);
- ASSERT_TRUE(broker);
- // Get the path to the sandboxed app.
- wchar_t prog_name[MAX_PATH];
- GetModuleFileNameW(nullptr, 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;
- ResultCode warning_result = SBOX_ALL_OK;
- base::win::ScopedProcessInformation target;
- auto policy = broker->CreatePolicy();
- policy->SetAlternateDesktop(true);
- policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN);
- PROCESS_INFORMATION temp_process_info = {};
- DWORD last_error = ERROR_SUCCESS;
- // Keep the desktop name for later.
- std::wstring desktop_name = policy->GetAlternateDesktop();
- result =
- broker->SpawnTarget(prog_name, arguments.c_str(), std::move(policy),
- &warning_result, &last_error, &temp_process_info);
- EXPECT_EQ(SBOX_ALL_OK, result);
- if (result == SBOX_ALL_OK)
- target.Set(temp_process_info);
- EXPECT_EQ(1u, ::ResumeThread(target.thread_handle()));
- EXPECT_EQ(static_cast<DWORD>(WAIT_TIMEOUT),
- ::WaitForSingleObject(target.process_handle(), 2000));
- EXPECT_NE(::GetThreadDesktop(target.thread_id()),
- ::GetThreadDesktop(::GetCurrentThreadId()));
- 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(desk);
- EXPECT_TRUE(::TerminateProcess(target.process_handle(), 0));
- ::WaitForSingleObject(target.process_handle(), INFINITE);
- // Close the desktop handle.
- broker->CreatePolicy()->DestroyAlternateDesktop();
- }
- // Creates multiple policies, with alternate desktops on both local and
- // alternate winstations.
- TEST(PolicyTargetTest, BothLocalAndAlternateWinstationDesktop) {
- BrokerServices* broker = GetBroker();
- auto policy1 = broker->CreatePolicy();
- auto policy2 = broker->CreatePolicy();
- auto policy3 = broker->CreatePolicy();
- ResultCode result;
- result = policy1->SetAlternateDesktop(false);
- EXPECT_EQ(SBOX_ALL_OK, result);
- result = policy2->SetAlternateDesktop(true);
- EXPECT_EQ(SBOX_ALL_OK, result);
- result = policy3->SetAlternateDesktop(false);
- EXPECT_EQ(SBOX_ALL_OK, result);
- std::wstring policy1_desktop_name = policy1->GetAlternateDesktop();
- std::wstring policy2_desktop_name = policy2->GetAlternateDesktop();
- // Extract only the "desktop name" portion of
- // "{winstation name}\\{desktop name}"
- EXPECT_NE(policy1_desktop_name.substr(
- policy1_desktop_name.find_first_of(L'\\') + 1),
- policy2_desktop_name.substr(
- policy2_desktop_name.find_first_of(L'\\') + 1));
- policy1->DestroyAlternateDesktop();
- policy2->DestroyAlternateDesktop();
- policy3->DestroyAlternateDesktop();
- }
- // Launches the app in the sandbox and share a handle with it. The app should
- // be able to use the handle.
- TEST(PolicyTargetTest, ShareHandleTest) {
- BrokerServices* broker = GetBroker();
- ASSERT_TRUE(broker);
- base::StringPiece contents = "Hello World";
- base::WritableSharedMemoryRegion writable_region =
- base::WritableSharedMemoryRegion::Create(contents.size());
- ASSERT_TRUE(writable_region.IsValid());
- base::WritableSharedMemoryMapping writable_mapping = writable_region.Map();
- ASSERT_TRUE(writable_mapping.IsValid());
- memcpy(writable_mapping.memory(), contents.data(), contents.size());
- // Get the path to the sandboxed app.
- wchar_t prog_name[MAX_PATH];
- GetModuleFileNameW(nullptr, prog_name, MAX_PATH);
- base::ReadOnlySharedMemoryRegion read_only_region =
- base::WritableSharedMemoryRegion::ConvertToReadOnly(
- std::move(writable_region));
- ASSERT_TRUE(read_only_region.IsValid());
- auto policy = broker->CreatePolicy();
- policy->AddHandleToShare(read_only_region.GetPlatformHandle());
- std::wstring arguments(L"\"");
- arguments += prog_name;
- arguments += L"\" -child 0 shared_memory_handle ";
- arguments += base::AsWString(base::NumberToString16(
- base::win::HandleToUint32(read_only_region.GetPlatformHandle())));
- // Launch the app.
- ResultCode result = SBOX_ALL_OK;
- ResultCode warning_result = SBOX_ALL_OK;
- base::win::ScopedProcessInformation target;
- policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN);
- PROCESS_INFORMATION temp_process_info = {};
- DWORD last_error = ERROR_SUCCESS;
- result =
- broker->SpawnTarget(prog_name, arguments.c_str(), std::move(policy),
- &warning_result, &last_error, &temp_process_info);
- EXPECT_EQ(SBOX_ALL_OK, result);
- if (result == SBOX_ALL_OK)
- target.Set(temp_process_info);
- EXPECT_EQ(1u, ::ResumeThread(target.thread_handle()));
- EXPECT_EQ(static_cast<DWORD>(WAIT_TIMEOUT),
- ::WaitForSingleObject(target.process_handle(), 2000));
- EXPECT_TRUE(::TerminateProcess(target.process_handle(), 0));
- ::WaitForSingleObject(target.process_handle(), INFINITE);
- }
- // Dummy target that just reports that's it spawned correctly.
- SBOX_TESTS_COMMAND int PolicyTargetTest_SetEffectiveToken(int argc,
- wchar_t** argv) {
- return SBOX_TEST_SUCCEEDED;
- }
- // Test whether after using SetEffectiveToken spawning a target works as
- // expected.
- TEST(PolicyTargetTest, SetEffectiveToken) {
- TestRunner runner;
- HANDLE token;
- // Get current process token.
- EXPECT_TRUE(
- ::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS, &token));
- // Setup token guard.
- base::win::ScopedHandle token_guard(token);
- // Set token and run target.
- runner.GetPolicy()->SetEffectiveToken(token_guard.Get());
- EXPECT_EQ(SBOX_TEST_SUCCEEDED,
- runner.RunTest(L"PolicyTargetTest_SetEffectiveToken"));
- }
- // Test if shared policies can be created by the broker.
- TEST(SharedTargetConfig, BrokerConfigManagement) {
- BrokerServices* broker = GetBroker();
- ASSERT_TRUE(broker);
- // Policies with empty names should not be fixed.
- auto policy = broker->CreatePolicy("");
- EXPECT_FALSE(policy->GetConfig()->IsConfigured());
- // Normally a policy is frozen (if necessary) by the broker when it is passed
- // to SpawnTarget.
- BrokerServicesBase::FreezeTargetConfigForTesting(policy->GetConfig());
- EXPECT_TRUE(policy->GetConfig()->IsConfigured());
- auto policy_two = broker->CreatePolicy("");
- EXPECT_FALSE(policy_two->GetConfig()->IsConfigured());
- // Policies with no name should not be fixed.
- policy = broker->CreatePolicy();
- EXPECT_FALSE(policy->GetConfig()->IsConfigured());
- BrokerServicesBase::FreezeTargetConfigForTesting(policy->GetConfig());
- policy_two = broker->CreatePolicy();
- EXPECT_FALSE(policy_two->GetConfig()->IsConfigured());
- // Named policy should not be fixed the first time.
- policy = broker->CreatePolicy("key-one");
- EXPECT_FALSE(policy->GetConfig()->IsConfigured());
- BrokerServicesBase::FreezeTargetConfigForTesting(policy->GetConfig());
- // Policy should be fixed the second time.
- policy = broker->CreatePolicy("key-one");
- EXPECT_TRUE(policy->GetConfig()->IsConfigured());
- // Even if all policies with the same key are deleted.
- policy.reset();
- policy = broker->CreatePolicy("key-one");
- EXPECT_TRUE(policy->GetConfig()->IsConfigured());
- // A different name should not be fixed the first time.
- policy_two = broker->CreatePolicy("key-two");
- EXPECT_FALSE(policy_two->GetConfig()->IsConfigured());
- BrokerServicesBase::FreezeTargetConfigForTesting(policy_two->GetConfig());
- // But should be the second time.
- policy_two = broker->CreatePolicy("key-two");
- EXPECT_TRUE(policy_two->GetConfig()->IsConfigured());
- }
- } // namespace sandbox
|