#include "sandbox/win/src/broker_services.h"
+#include <AclAPI.h>
+
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/threading/platform_thread.h"
}
}
+// Utility function to determine whether a token for the specified policy can
+// be cached.
+bool IsTokenCacheable(const sandbox::PolicyBase* policy) {
+ const sandbox::AppContainerAttributes* app_container =
+ policy->GetAppContainer();
+
+ // We cannot cache tokens with an app container.
+ if (app_container)
+ return false;
+
+ return true;
+}
+
+// Utility function to pack token values into a key for the cache map.
+uint32_t GenerateTokenCacheKey(const sandbox::PolicyBase* policy) {
+ const size_t kTokenShift = 3;
+ uint32_t key;
+
+ DCHECK(IsTokenCacheable(policy));
+
+ // Make sure our token values aren't too large to pack into the key.
+ static_assert(sandbox::USER_LAST <= (1 << kTokenShift),
+ "TokenLevel too large");
+ static_assert(sandbox::INTEGRITY_LEVEL_LAST <= (1 << kTokenShift),
+ "IntegrityLevel too large");
+ static_assert(sizeof(key) < (kTokenShift * 3),
+ "Token key type too small");
+
+ // The key is the enum values shifted to avoid overlap and OR'd together.
+ key = policy->GetInitialTokenLevel();
+ key <<= kTokenShift;
+ key |= policy->GetLockdownTokenLevel();
+ key <<= kTokenShift;
+ key |= policy->GetIntegrityLevel();
+
+ return key;
+}
+
} // namespace
namespace sandbox {
// If job_port_ isn't NULL, assumes that the lock has been initialized.
if (job_port_)
::DeleteCriticalSection(&lock_);
+
+ // Close any token in the cache.
+ for (TokenCacheMap::iterator it = token_cache_.begin();
+ it != token_cache_.end(); ++it) {
+ ::CloseHandle(it->second.first);
+ ::CloseHandle(it->second.second);
+ }
}
TargetPolicy* BrokerServicesBase::CreatePolicy() {
break;
}
+ case JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT: {
+ BOOL res = ::TerminateJobObject(tracker->job,
+ SBOX_FATAL_MEMORY_EXCEEDED);
+ DCHECK(res);
+ break;
+ }
+
default: {
NOTREACHED();
break;
// with the soon to be created target process.
HANDLE initial_token_temp;
HANDLE lockdown_token_temp;
- ResultCode result = policy_base->MakeTokens(&initial_token_temp,
- &lockdown_token_temp);
- if (SBOX_ALL_OK != result)
- return result;
+ ResultCode result = SBOX_ALL_OK;
+
+ if (IsTokenCacheable(policy_base)) {
+ // Create the master tokens only once and save them in a cache. That way
+ // can just duplicate them to avoid hammering LSASS on every sandboxed
+ // process launch.
+ uint32_t token_key = GenerateTokenCacheKey(policy_base);
+ TokenCacheMap::iterator it = token_cache_.find(token_key);
+ if (it != token_cache_.end()) {
+ initial_token_temp = it->second.first;
+ lockdown_token_temp = it->second.second;
+ } else {
+ result =
+ policy_base->MakeTokens(&initial_token_temp, &lockdown_token_temp);
+ if (SBOX_ALL_OK != result)
+ return result;
+ token_cache_[token_key] =
+ std::pair<HANDLE, HANDLE>(initial_token_temp, lockdown_token_temp);
+ }
+
+ if (!::DuplicateToken(initial_token_temp, SecurityImpersonation,
+ &initial_token_temp)) {
+ return SBOX_ERROR_GENERIC;
+ }
+
+ if (!::DuplicateTokenEx(lockdown_token_temp, TOKEN_ALL_ACCESS, 0,
+ SecurityIdentification, TokenPrimary,
+ &lockdown_token_temp)) {
+ return SBOX_ERROR_GENERIC;
+ }
+ } else {
+ result = policy_base->MakeTokens(&initial_token_temp, &lockdown_token_temp);
+ if (SBOX_ALL_OK != result)
+ return result;
+ }
base::win::ScopedHandle initial_token(initial_token_temp);
base::win::ScopedHandle lockdown_token(lockdown_token_temp);
// Initialize the startup information from the policy.
base::win::StartupInformation startup_info;
- string16 desktop = policy_base->GetAlternateDesktop();
+ base::string16 desktop = policy_base->GetAlternateDesktop();
if (!desktop.empty()) {
startup_info.startup_info()->lpDesktop =
const_cast<wchar_t*>(desktop.c_str());
base::win::ScopedProcessInformation process_info;
TargetProcess* target = new TargetProcess(initial_token.Take(),
lockdown_token.Take(),
- job,
+ job.Get(),
thread_pool_);
DWORD win_result = target->Create(exe_path, command_line, inherit_handles,
return SBOX_ERROR_BAD_PARAMS;
if (!::RegisterWaitForSingleObject(
- &peer->wait_object, peer->process, RemovePeer, peer.get(), INFINITE,
- WT_EXECUTEONLYONCE | WT_EXECUTEINWAITTHREAD)) {
+ &peer->wait_object, peer->process.Get(), RemovePeer, peer.get(),
+ INFINITE, WT_EXECUTEONLYONCE | WT_EXECUTEINWAITTHREAD)) {
peer_map_.erase(peer->id);
return SBOX_ERROR_GENERIC;
}
if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8)
return SBOX_ERROR_UNSUPPORTED;
- string16 old_name = LookupAppContainer(sid);
+ base::string16 old_name = LookupAppContainer(sid);
if (old_name.empty())
return CreateAppContainer(sid, name);
if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8)
return SBOX_ERROR_UNSUPPORTED;
- string16 name = LookupAppContainer(sid);
+ base::string16 name = LookupAppContainer(sid);
if (name.empty())
return SBOX_ERROR_INVALID_APP_CONTAINER;