Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / sandbox / win / src / broker_services.cc
index 921eb4f..8fa7f0d 100644 (file)
@@ -4,6 +4,8 @@
 
 #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"
@@ -80,6 +82,44 @@ void DeregisterPeerTracker(PeerTracker* peer) {
   }
 }
 
+// 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 {
@@ -153,6 +193,13 @@ BrokerServicesBase::~BrokerServicesBase() {
   // 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() {
@@ -246,6 +293,13 @@ DWORD WINAPI BrokerServicesBase::TargetEventsThread(PVOID param) {
           break;
         }
 
+        case JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT: {
+          BOOL res = ::TerminateJobObject(tracker->job,
+                                          SBOX_FATAL_MEMORY_EXCEEDED);
+          DCHECK(res);
+          break;
+        }
+
         default: {
           NOTREACHED();
           break;
@@ -299,10 +353,41 @@ ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path,
   // 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);
@@ -316,7 +401,7 @@ ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path,
 
   // 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());
@@ -393,7 +478,7 @@ ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path,
   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,
@@ -470,8 +555,8 @@ ResultCode BrokerServicesBase::AddTargetPeer(HANDLE peer_process) {
     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;
   }
@@ -486,7 +571,7 @@ ResultCode BrokerServicesBase::InstallAppContainer(const wchar_t* sid,
   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);
 
@@ -500,7 +585,7 @@ ResultCode BrokerServicesBase::UninstallAppContainer(const wchar_t* sid) {
   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;