diff options
author | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-28 21:34:10 +0000 |
---|---|---|
committer | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-28 21:34:10 +0000 |
commit | 860f561694cbcbecf29781381f0dfff84ff9ce82 (patch) | |
tree | 7bd1ce5d59faf8beead7a860ae1862622d55a3ab /sandbox | |
parent | 90637900afda69bccf5ef9200585e72e01c2f2d6 (diff) | |
download | chromium_src-860f561694cbcbecf29781381f0dfff84ff9ce82.zip chromium_src-860f561694cbcbecf29781381f0dfff84ff9ce82.tar.gz chromium_src-860f561694cbcbecf29781381f0dfff84ff9ce82.tar.bz2 |
Sandbox: Move code around.
This is mostly a NOP, except for the initialization of
ui_exceptions_.
BUG=none
TEST=none
Review URL: https://chromiumcodereview.appspot.com/10697013
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@144804 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox')
-rw-r--r-- | sandbox/src/sandbox_policy.h | 92 | ||||
-rw-r--r-- | sandbox/src/sandbox_policy_base.cc | 250 | ||||
-rw-r--r-- | sandbox/src/sandbox_policy_base.h | 112 |
3 files changed, 236 insertions, 218 deletions
diff --git a/sandbox/src/sandbox_policy.h b/sandbox/src/sandbox_policy.h index ced8acb..288adc45 100644 --- a/sandbox/src/sandbox_policy.h +++ b/sandbox/src/sandbox_policy.h @@ -15,6 +15,45 @@ namespace sandbox { class TargetPolicy { public: + // Windows subsystems that can have specific rules. + // Note: The process subsystem(SUBSY_PROCESS) does not evaluate the request + // exactly like the CreateProcess API does. See the comment at the top of + // process_thread_dispatcher.cc for more details. + enum SubSystem { + SUBSYS_FILES, // Creation and opening of files and pipes. + SUBSYS_NAMED_PIPES, // Creation of named pipes. + SUBSYS_PROCESS, // Creation of child processes. + SUBSYS_REGISTRY, // Creation and opening of registry keys. + SUBSYS_SYNC, // Creation of named sync objects. + SUBSYS_HANDLES // Duplication of handles to other processes. + }; + + // Allowable semantics when a rule is matched. + enum Semantics { + FILES_ALLOW_ANY, // Allows open or create for any kind of access that + // the file system supports. + FILES_ALLOW_READONLY, // Allows open or create with read access only. + FILES_ALLOW_QUERY, // Allows access to query the attributes of a file. + FILES_ALLOW_DIR_ANY, // Allows open or create with directory semantics + // only. + HANDLES_DUP_ANY, // Allows duplicating handles opened with any + // access permissions. + HANDLES_DUP_BROKER, // Allows duplicating handles to the broker process. + NAMEDPIPES_ALLOW_ANY, // Allows creation of a named pipe. + PROCESS_MIN_EXEC, // Allows to create a process with minimal rights + // over the resulting process and thread handles. + // No other parameters besides the command line are + // passed to the child process. + PROCESS_ALL_EXEC, // Allows the creation of a process and return fill + // access on the returned handles. + // This flag can be used only when the main token of + // the sandboxed application is at least INTERACTIVE. + EVENTS_ALLOW_ANY, // Allows the creation of an event with full access. + EVENTS_ALLOW_READONLY, // Allows opening an even with synchronize access. + REG_ALLOW_READONLY, // Allows readonly access to a registry key. + REG_ALLOW_ANY // Allows read and write access to a registry key. + }; + // Increments the reference count of this object. The reference count must // be incremented if this interface is given to another component. virtual void AddRef() = 0; @@ -97,6 +136,13 @@ class TargetPolicy { // Destroys the desktop and windows station. virtual void DestroyAlternateDesktop() = 0; + // Sets the integrity level of the process in the sandbox. Both the initial + // token and the main token will be affected by this. This is valid only + // on Vista. It is silently ignored on other OSes. If you set the integrity + // level to a level higher than your current level, the sandbox will fail + // to start. + virtual ResultCode SetIntegrityLevel(IntegrityLevel level) = 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 // Isolation is not affected by this setting and will remain off for the @@ -105,13 +151,6 @@ class TargetPolicy { // than your current level, the sandbox will fail to start. virtual ResultCode SetDelayedIntegrityLevel(IntegrityLevel level) = 0; - // Sets the integrity level of the process in the sandbox. Both the initial - // token and the main token will be affected by this. This is valid only - // on Vista. It is silently ignored on other OSes. If you set the integrity - // level to a level higher than your current level, the sandbox will fail - // to start. - virtual ResultCode SetIntegrityLevel(IntegrityLevel level) = 0; - // Sets the interceptions to operate in strict mode. By default, interceptions // are performed in "relaxed" mode, where if something inside NTDLL.DLL is // already patched we attempt to intercept it anyway. Setting interceptions @@ -119,45 +158,6 @@ class TargetPolicy { // refuse to perform the interception. virtual void SetStrictInterceptions() = 0; - // Windows subsystems that can have specific rules. - // Note: The process subsystem(SUBSY_PROCESS) does not evaluate the request - // exactly like the CreateProcess API does. See the comment at the top of - // process_thread_dispatcher.cc for more details. - enum SubSystem { - SUBSYS_FILES, // Creation and opening of files and pipes. - SUBSYS_NAMED_PIPES, // Creation of named pipes. - SUBSYS_PROCESS, // Creation of child processes. - SUBSYS_REGISTRY, // Creation and opening of registry keys. - SUBSYS_SYNC, // Creation of named sync objects. - SUBSYS_HANDLES // Duplication of handles to other processes. - }; - - // Allowable semantics when a rule is matched. - enum Semantics { - FILES_ALLOW_ANY, // Allows open or create for any kind of access that - // the file system supports. - FILES_ALLOW_READONLY, // Allows open or create with read access only. - FILES_ALLOW_QUERY, // Allows access to query the attributes of a file. - FILES_ALLOW_DIR_ANY, // Allows open or create with directory semantics - // only. - HANDLES_DUP_ANY, // Allows duplicating handles opened with any - // access permissions. - HANDLES_DUP_BROKER, // Allows duplicating handles to the broker process. - NAMEDPIPES_ALLOW_ANY, // Allows creation of a named pipe. - PROCESS_MIN_EXEC, // Allows to create a process with minimal rights - // over the resulting process and thread handles. - // No other parameters besides the command line are - // passed to the child process. - PROCESS_ALL_EXEC, // Allows the creation of a process and return fill - // access on the returned handles. - // This flag can be used only when the main token of - // the sandboxed application is at least INTERACTIVE. - EVENTS_ALLOW_ANY, // Allows the creation of an event with full access. - EVENTS_ALLOW_READONLY, // Allows opening an even with synchronize access. - REG_ALLOW_READONLY, // Allows readonly access to a registry key. - REG_ALLOW_ANY // Allows read and write access to a registry key. - }; - // Adds a policy rule effective for processes spawned using this policy. // subsystem: One of the above enumerated windows subsystems. // semantics: One of the above enumerated FileSemantics. diff --git a/sandbox/src/sandbox_policy_base.cc b/sandbox/src/sandbox_policy_base.cc index 587d59d..4438641 100644 --- a/sandbox/src/sandbox_policy_base.cc +++ b/sandbox/src/sandbox_policy_base.cc @@ -61,14 +61,15 @@ PolicyBase::PolicyBase() lockdown_level_(USER_LOCKDOWN), initial_level_(USER_LOCKDOWN), job_level_(JOB_LOCKDOWN), + ui_exceptions_(0), + use_alternate_desktop_(false), + use_alternate_winstation_(false), + file_system_init_(false), + relaxed_interceptions_(true), integrity_level_(INTEGRITY_LEVEL_LAST), delayed_integrity_level_(INTEGRITY_LEVEL_LAST), - policy_(NULL), policy_maker_(NULL), - file_system_init_(false), - relaxed_interceptions_(true), - use_alternate_desktop_(false), - use_alternate_winstation_(false) { + policy_(NULL) { ::InitializeCriticalSection(&lock_); // Initialize the IPC dispatcher array. memset(&ipc_targets_, NULL, sizeof(ipc_targets_)); @@ -120,37 +121,36 @@ PolicyBase::~PolicyBase() { ::DeleteCriticalSection(&lock_); } -DWORD PolicyBase::MakeJobObject(HANDLE* job) { - // Create the windows job object. - Job job_obj; - DWORD result = job_obj.Init(job_level_, NULL, ui_exceptions_); - if (ERROR_SUCCESS != result) { - return result; - } - *job = job_obj.Detach(); - return ERROR_SUCCESS; +void PolicyBase::AddRef() { + ::InterlockedIncrement(&ref_count); } -DWORD PolicyBase::MakeTokens(HANDLE* initial, HANDLE* lockdown) { - // Create the 'naked' token. This will be the permanent token associated - // with the process and therefore with any thread that is not impersonating. - DWORD result = CreateRestrictedToken(lockdown, lockdown_level_, - integrity_level_, PRIMARY); - if (ERROR_SUCCESS != result) { - return result; - } - // Create the 'better' token. We use this token as the one that the main - // thread uses when booting up the process. It should contain most of - // what we need (before reaching main( )) - result = CreateRestrictedToken(initial, initial_level_, - integrity_level_, IMPERSONATION); - if (ERROR_SUCCESS != result) { - ::CloseHandle(*lockdown); - return result; +void PolicyBase::Release() { + if (0 == ::InterlockedDecrement(&ref_count)) + delete this; +} + +ResultCode PolicyBase::SetTokenLevel(TokenLevel initial, TokenLevel lockdown) { + if (initial < lockdown) { + return SBOX_ERROR_BAD_PARAMS; } + initial_level_ = initial; + lockdown_level_ = lockdown; return SBOX_ALL_OK; } +ResultCode PolicyBase::SetJobLevel(JobLevel job_level, uint32 ui_exceptions) { + job_level_ = job_level; + ui_exceptions_ = ui_exceptions; + return SBOX_ALL_OK; +} + +ResultCode PolicyBase::SetAlternateDesktop(bool alternate_winstation) { + use_alternate_desktop_ = true; + use_alternate_winstation_ = alternate_winstation; + return CreateAlternateDesktop(alternate_winstation); +} + std::wstring PolicyBase::GetAlternateDesktop() const { // No alternate desktop or winstation. Return an empty string. if (!use_alternate_desktop_ && !use_alternate_winstation_) { @@ -226,48 +226,31 @@ ResultCode PolicyBase::CreateAlternateDesktop(bool alternate_winstation) { return SBOX_ALL_OK; } -bool PolicyBase::AddTarget(TargetProcess* target) { - if (NULL != policy_) - policy_maker_->Done(); - - if (!SetupAllInterceptions(target)) - return false; - - if (!SetupHandleCloser(target)) - return false; +void PolicyBase::DestroyAlternateDesktop() { + if (alternate_desktop_handle_) { + ::CloseDesktop(alternate_desktop_handle_); + alternate_desktop_handle_ = NULL; + } - // Initialize the sandbox infrastructure for the target. - if (ERROR_SUCCESS != target->Init(this, policy_, kIPCMemSize, kPolMemSize)) - return false; + if (alternate_winstation_handle_) { + ::CloseWindowStation(alternate_winstation_handle_); + alternate_winstation_handle_ = NULL; + } +} - g_shared_delayed_integrity_level = delayed_integrity_level_; - ResultCode ret = target->TransferVariable( - "g_shared_delayed_integrity_level", - &g_shared_delayed_integrity_level, - sizeof(g_shared_delayed_integrity_level)); - g_shared_delayed_integrity_level = INTEGRITY_LEVEL_LAST; - if (SBOX_ALL_OK != ret) - return false; +ResultCode PolicyBase::SetIntegrityLevel(IntegrityLevel integrity_level) { + integrity_level_ = integrity_level; + return SBOX_ALL_OK; +} - AutoLock lock(&lock_); - targets_.push_back(target); - return true; +ResultCode PolicyBase::SetDelayedIntegrityLevel( + IntegrityLevel integrity_level) { + delayed_integrity_level_ = integrity_level; + return SBOX_ALL_OK; } -bool PolicyBase::OnJobEmpty(HANDLE job) { - AutoLock lock(&lock_); - TargetSet::iterator it; - for (it = targets_.begin(); it != targets_.end(); ++it) { - if ((*it)->Job() == job) - break; - } - if (it == targets_.end()) { - return false; - } - TargetProcess* target = *it; - targets_.erase(it); - delete target; - return true; +void PolicyBase::SetStrictInterceptions() { + relaxed_interceptions_ = false; } ResultCode PolicyBase::AddRule(SubSystem subsystem, Semantics semantics, @@ -341,31 +324,14 @@ ResultCode PolicyBase::AddRule(SubSystem subsystem, Semantics semantics, return SBOX_ALL_OK; } -EvalResult PolicyBase::EvalPolicy(int service, - CountedParameterSetBase* params) { - if (NULL != policy_) { - if (NULL == policy_->entry[service]) { - // There is no policy for this particular service. This is not a big - // deal. - return DENY_ACCESS; - } - for (int i = 0; i < params->count; i++) { - if (!params->parameters[i].IsValid()) { - NOTREACHED(); - return SIGNAL_ALARM; - } - } - PolicyProcessor pol_evaluator(policy_->entry[service]); - PolicyResult result = pol_evaluator.Evaluate(kShortEval, - params->parameters, - params->count); - if (POLICY_MATCH == result) { - return pol_evaluator.GetAction(); - } - DCHECK(POLICY_ERROR != result); - } +ResultCode PolicyBase::AddDllToUnload(const wchar_t* dll_name) { + blacklisted_dlls_.push_back(std::wstring(dll_name)); + return SBOX_ALL_OK; +} - return DENY_ACCESS; +ResultCode PolicyBase::AddKernelObjectToClose(const char16* handle_type, + const char16* handle_name) { + return handle_closer_.AddHandle(handle_type, handle_name); } // When an IPC is ready in any of the targets we get called. We manage an array @@ -404,6 +370,108 @@ bool PolicyBase::SetupService(InterceptionManager* manager, int service) { return dispatch->SetupService(manager, service); } +DWORD PolicyBase::MakeJobObject(HANDLE* job) { + // Create the windows job object. + Job job_obj; + DWORD result = job_obj.Init(job_level_, NULL, ui_exceptions_); + if (ERROR_SUCCESS != result) { + return result; + } + *job = job_obj.Detach(); + return ERROR_SUCCESS; +} + +DWORD PolicyBase::MakeTokens(HANDLE* initial, HANDLE* lockdown) { + // Create the 'naked' token. This will be the permanent token associated + // with the process and therefore with any thread that is not impersonating. + DWORD result = CreateRestrictedToken(lockdown, lockdown_level_, + integrity_level_, PRIMARY); + if (ERROR_SUCCESS != result) { + return result; + } + // Create the 'better' token. We use this token as the one that the main + // thread uses when booting up the process. It should contain most of + // what we need (before reaching main( )) + result = CreateRestrictedToken(initial, initial_level_, + integrity_level_, IMPERSONATION); + if (ERROR_SUCCESS != result) { + ::CloseHandle(*lockdown); + return result; + } + return SBOX_ALL_OK; +} + +bool PolicyBase::AddTarget(TargetProcess* target) { + if (NULL != policy_) + policy_maker_->Done(); + + if (!SetupAllInterceptions(target)) + return false; + + if (!SetupHandleCloser(target)) + return false; + + // Initialize the sandbox infrastructure for the target. + if (ERROR_SUCCESS != target->Init(this, policy_, kIPCMemSize, kPolMemSize)) + return false; + + g_shared_delayed_integrity_level = delayed_integrity_level_; + ResultCode ret = target->TransferVariable( + "g_shared_delayed_integrity_level", + &g_shared_delayed_integrity_level, + sizeof(g_shared_delayed_integrity_level)); + g_shared_delayed_integrity_level = INTEGRITY_LEVEL_LAST; + if (SBOX_ALL_OK != ret) + return false; + + AutoLock lock(&lock_); + targets_.push_back(target); + return true; +} + +bool PolicyBase::OnJobEmpty(HANDLE job) { + AutoLock lock(&lock_); + TargetSet::iterator it; + for (it = targets_.begin(); it != targets_.end(); ++it) { + if ((*it)->Job() == job) + break; + } + if (it == targets_.end()) { + return false; + } + TargetProcess* target = *it; + targets_.erase(it); + delete target; + return true; +} + +EvalResult PolicyBase::EvalPolicy(int service, + CountedParameterSetBase* params) { + if (NULL != policy_) { + if (NULL == policy_->entry[service]) { + // There is no policy for this particular service. This is not a big + // deal. + return DENY_ACCESS; + } + for (int i = 0; i < params->count; i++) { + if (!params->parameters[i].IsValid()) { + NOTREACHED(); + return SIGNAL_ALARM; + } + } + PolicyProcessor pol_evaluator(policy_->entry[service]); + PolicyResult result = pol_evaluator.Evaluate(kShortEval, + params->parameters, + params->count); + if (POLICY_MATCH == result) { + return pol_evaluator.GetAction(); + } + DCHECK(POLICY_ERROR != result); + } + + return DENY_ACCESS; +} + // We service IPC_PING_TAG message which is a way to test a round trip of the // IPC subsystem. We receive a integer cookie and we are expected to return the // cookie times two (or three) and the current tick count. diff --git a/sandbox/src/sandbox_policy_base.h b/sandbox/src/sandbox_policy_base.h index 2f635f5..b3ea805 100644 --- a/sandbox/src/sandbox_policy_base.h +++ b/sandbox/src/sandbox_policy_base.h @@ -11,6 +11,7 @@ #include <vector> #include "base/basictypes.h" +#include "base/compiler_specific.h" #include "base/string16.h" #include "sandbox/src/crosscall_server.h" #include "sandbox/src/handle_closer.h" @@ -34,100 +35,50 @@ class PolicyBase : public Dispatcher, public TargetPolicy { public: PolicyBase(); - virtual void AddRef() { - ::InterlockedIncrement(&ref_count); - } - - virtual void Release() { - if (0 == ::InterlockedDecrement(&ref_count)) - delete this; - } - - virtual ResultCode SetTokenLevel(TokenLevel initial, TokenLevel lockdown) { - if (initial < lockdown) { - return SBOX_ERROR_BAD_PARAMS; - } - initial_level_ = initial; - lockdown_level_ = lockdown; - return SBOX_ALL_OK; - } - - virtual ResultCode SetJobLevel(JobLevel job_level, uint32 ui_exceptions) { - job_level_ = job_level; - ui_exceptions_ = ui_exceptions; - 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) { - integrity_level_ = integrity_level; - return SBOX_ALL_OK; - } - - virtual ResultCode SetDelayedIntegrityLevel(IntegrityLevel integrity_level) { - delayed_integrity_level_ = integrity_level; - return SBOX_ALL_OK; - } - - virtual void SetStrictInterceptions() { - relaxed_interceptions_ = false; - } - + // TargetPolicy: + virtual void AddRef() OVERRIDE; + virtual void Release() OVERRIDE; + virtual ResultCode SetTokenLevel(TokenLevel initial, + TokenLevel lockdown) OVERRIDE; + virtual ResultCode SetJobLevel(JobLevel job_level, + uint32 ui_exceptions) OVERRIDE; + virtual ResultCode SetAlternateDesktop(bool alternate_winstation) OVERRIDE; + virtual std::wstring GetAlternateDesktop() const OVERRIDE; + virtual ResultCode CreateAlternateDesktop(bool alternate_winstation) OVERRIDE; + virtual void DestroyAlternateDesktop() OVERRIDE; + virtual ResultCode SetIntegrityLevel(IntegrityLevel integrity_level) OVERRIDE; + virtual ResultCode SetDelayedIntegrityLevel( + IntegrityLevel integrity_level) OVERRIDE; + virtual void SetStrictInterceptions() OVERRIDE; virtual ResultCode AddRule(SubSystem subsystem, Semantics semantics, - const wchar_t* pattern); - - virtual ResultCode AddDllToUnload(const wchar_t* dll_name) { - blacklisted_dlls_.push_back(std::wstring(dll_name)); - return SBOX_ALL_OK; - } - + const wchar_t* pattern) OVERRIDE; + virtual ResultCode AddDllToUnload(const wchar_t* dll_name); virtual ResultCode AddKernelObjectToClose(const char16* handle_type, - const char16* handle_name) { - return handle_closer_.AddHandle(handle_type, handle_name); - } + const char16* handle_name) OVERRIDE; + + // Dispatcher: + virtual Dispatcher* OnMessageReady(IPCParams* ipc, + CallbackGeneric* callback) OVERRIDE; + virtual bool SetupService(InterceptionManager* manager, int service) OVERRIDE; // Creates a Job object with the level specified in a previous call to // SetJobLevel(). Returns the standard windows of ::GetLastError(). DWORD MakeJobObject(HANDLE* job); + // Creates the two tokens with the levels specified in a previous call to // SetTokenLevel(). Returns the standard windows of ::GetLastError(). DWORD MakeTokens(HANDLE* initial, HANDLE* lockdown); + // Adds a target process to the internal list of targets. Internally a // call to TargetProcess::Init() is issued. bool AddTarget(TargetProcess* target); + // Called when there are no more active processes in a Job. // Removes a Job object associated with this policy and the target associated // with the job. bool OnJobEmpty(HANDLE job); - // Overrides Dispatcher::OnMessageReady. - virtual Dispatcher* OnMessageReady(IPCParams* ipc, CallbackGeneric* callback); - - // Dispatcher interface. - virtual bool SetupService(InterceptionManager* manager, int service); - - virtual EvalResult EvalPolicy(int service, CountedParameterSetBase* params); + EvalResult EvalPolicy(int service, CountedParameterSetBase* params); private: ~PolicyBase(); @@ -159,6 +110,9 @@ class PolicyBase : public Dispatcher, public TargetPolicy { uint32 ui_exceptions_; bool use_alternate_desktop_; bool use_alternate_winstation_; + // Helps the file system policy initialization. + bool file_system_init_; + bool relaxed_interceptions_; IntegrityLevel integrity_level_; IntegrityLevel delayed_integrity_level_; // The array of objects that will answer IPC calls. @@ -167,10 +121,6 @@ class PolicyBase : public Dispatcher, public TargetPolicy { LowLevelPolicy* policy_maker_; // Memory structure that stores the low level policy. PolicyGlobal* policy_; - // Helps the file system policy initialization. - bool file_system_init_; - // Operation mode for the interceptions. - bool relaxed_interceptions_; // The list of dlls to unload in the target process. std::vector<std::wstring> blacklisted_dlls_; // This is a map of handle-types to names that we need to close in the |