From 51a5fe52f3ca65660195e4a0676020c7fed0cc19 Mon Sep 17 00:00:00 2001 From: Bob Owen Date: Fri, 22 May 2015 17:05:45 +0100 Subject: [PATCH] Bug 1123759: Set low integrity on NPAPI processes for Windows sandboxing policy level >= 2. r=bbondy, r=bsmedberg --- browser/app/profile/firefox.js | 5 +- dom/plugins/ipc/PluginModuleParent.cpp | 14 ++- dom/plugins/ipc/PluginModuleParent.h | 4 +- dom/plugins/ipc/PluginProcessParent.cpp | 18 ++- .../win/src/sandboxbroker/sandboxBroker.cpp | 106 ++++++++++-------- 5 files changed, 88 insertions(+), 59 deletions(-) diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index ef41a179c1ae..77c4da455019 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1198,9 +1198,10 @@ pref("security.sandbox.windows.log", false); // On windows these levels are: // 0 - no sandbox // 1 - sandbox with USER_NON_ADMIN access token level -// 2 - a more strict sandbox, which might cause functionality issues +// 2 - a more strict sandbox, which might cause functionality issues. This now +// includes running at low integrity. // 3 - the strongest settings we seem to be able to use without breaking -// everything, but will definitely cause some functionality restrictions +// everything, but will probably cause some functionality restrictions pref("dom.ipc.plugins.sandbox-level.default", 0); #if defined(MOZ_CONTENT_SANDBOX) diff --git a/dom/plugins/ipc/PluginModuleParent.cpp b/dom/plugins/ipc/PluginModuleParent.cpp index dafd785fbe5a..185195bb0333 100755 --- a/dom/plugins/ipc/PluginModuleParent.cpp +++ b/dom/plugins/ipc/PluginModuleParent.cpp @@ -481,7 +481,8 @@ PluginModuleChromeParent::LoadModule(const char* aFilePath, uint32_t aPluginId, } #endif - nsAutoPtr parent(new PluginModuleChromeParent(aFilePath, aPluginId)); + nsAutoPtr parent(new PluginModuleChromeParent(aFilePath, aPluginId, + sandboxLevel)); UniquePtr onLaunchedRunnable(new LaunchedTask(parent)); parent->mSubprocess->SetCallRunnableImmediately(!parent->mIsStartingAsync); TimeStamp launchStart = TimeStamp::Now(); @@ -564,9 +565,11 @@ PluginModuleChromeParent::OnProcessLaunched(const bool aSucceeded) #endif #endif -#ifdef XP_WIN +#if defined(XP_WIN) && defined(_X86_) + // Protected mode only applies to Windows and only to x86. if (!mIsBlocklisted && mIsFlashPlugin && - Preferences::GetBool("dom.ipc.plugins.flash.disable-protected-mode", false)) { + (Preferences::GetBool("dom.ipc.plugins.flash.disable-protected-mode", false) || + mSandboxLevel >= 2)) { SendDisableFlashProtectedMode(); } #endif @@ -662,7 +665,9 @@ PluginModuleContentParent::~PluginModuleContentParent() bool PluginModuleChromeParent::sInstantiated = false; -PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath, uint32_t aPluginId) +PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath, + uint32_t aPluginId, + int32_t aSandboxLevel) : PluginModuleParent(true) , mSubprocess(new PluginProcessParent(aFilePath)) , mPluginId(aPluginId) @@ -674,6 +679,7 @@ PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath, uint32 , mHangUIParent(nullptr) , mHangUIEnabled(true) , mIsTimerReset(true) + , mSandboxLevel(aSandboxLevel) #ifdef MOZ_CRASHREPORTER , mCrashReporterMutex("PluginModuleChromeParent::mCrashReporterMutex") , mCrashReporter(nullptr) diff --git a/dom/plugins/ipc/PluginModuleParent.h b/dom/plugins/ipc/PluginModuleParent.h index ee19141564e8..2a5d86192923 100644 --- a/dom/plugins/ipc/PluginModuleParent.h +++ b/dom/plugins/ipc/PluginModuleParent.h @@ -443,7 +443,8 @@ private: virtual void ActorDestroy(ActorDestroyReason why) override; // aFilePath is UTF8, not native! - explicit PluginModuleChromeParent(const char* aFilePath, uint32_t aPluginId); + explicit PluginModuleChromeParent(const char* aFilePath, uint32_t aPluginId, + int32_t aSandboxLevel); CrashReporterParent* CrashReporter(); @@ -483,6 +484,7 @@ private: PluginHangUIParent *mHangUIParent; bool mHangUIEnabled; bool mIsTimerReset; + int32_t mSandboxLevel; #ifdef MOZ_CRASHREPORTER /** * This mutex protects the crash reporter when the Plugin Hang UI event diff --git a/dom/plugins/ipc/PluginProcessParent.cpp b/dom/plugins/ipc/PluginProcessParent.cpp index 39e09bb12abe..ac8399e334f0 100644 --- a/dom/plugins/ipc/PluginProcessParent.cpp +++ b/dom/plugins/ipc/PluginProcessParent.cpp @@ -76,7 +76,7 @@ AddSandboxAllowedFiles(int32_t aSandboxLevel, vector& aAllowedFilesRead, vector& aAllowedFilesReadWrite) { - if (aSandboxLevel < 3) { + if (aSandboxLevel < 2) { return; } @@ -87,16 +87,26 @@ AddSandboxAllowedFiles(int32_t aSandboxLevel, return; } - AddSandboxAllowedFile(aAllowedFilesRead, dirSvc, NS_WIN_HOME_DIR); - AddSandboxAllowedFile(aAllowedFilesRead, dirSvc, NS_WIN_HOME_DIR, - NS_LITERAL_STRING("\\*")); + // Higher than level 2 currently removes the users own rights. + if (aSandboxLevel > 2) { + AddSandboxAllowedFile(aAllowedFilesRead, dirSvc, NS_WIN_HOME_DIR); + AddSandboxAllowedFile(aAllowedFilesRead, dirSvc, NS_WIN_HOME_DIR, + NS_LITERAL_STRING("\\*")); + } + // Level 2 and above is now using low integrity, so we need to give write + // access to the Flash directories. AddSandboxAllowedFile(aAllowedFilesReadWrite, dirSvc, NS_WIN_APPDATA_DIR, NS_LITERAL_STRING("\\Macromedia\\Flash Player\\*")); AddSandboxAllowedFile(aAllowedFilesReadWrite, dirSvc, NS_WIN_APPDATA_DIR, NS_LITERAL_STRING("\\Adobe\\Flash Player\\*")); + +#if defined(_X86_) + // Write access to the Temp directory should only be needed for 32-bit as + // it is used to turn off protected mode, which only applies to x86. AddSandboxAllowedFile(aAllowedFilesReadWrite, dirSvc, NS_OS_TEMP_DIR, NS_LITERAL_STRING("\\*")); +#endif } #endif diff --git a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp index 5d442b6c6820..c7bc9871d107 100644 --- a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp +++ b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp @@ -162,57 +162,55 @@ SandboxBroker::SetSecurityLevelForPluginProcess(int32_t aSandboxLevel) return false; } - sandbox::ResultCode result; - bool ret; - if (aSandboxLevel >= 2) { - result = mPolicy->SetJobLevel(sandbox::JOB_UNPROTECTED, - 0 /* ui_exceptions */); - ret = (sandbox::SBOX_ALL_OK == result); - - sandbox::TokenLevel tokenLevel; - if (aSandboxLevel >= 3) { - tokenLevel = sandbox::USER_LIMITED; - } else { - tokenLevel = sandbox::USER_INTERACTIVE; - } - - result = mPolicy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS, - tokenLevel); - ret = ret && (sandbox::SBOX_ALL_OK == result); - - sandbox::MitigationFlags mitigations = - sandbox::MITIGATION_BOTTOM_UP_ASLR | - sandbox::MITIGATION_HEAP_TERMINATE | - sandbox::MITIGATION_SEHOP | - sandbox::MITIGATION_DEP_NO_ATL_THUNK | - sandbox::MITIGATION_DEP; - - result = mPolicy->SetProcessMitigations(mitigations); - ret = ret && (sandbox::SBOX_ALL_OK == result); - - mitigations = - sandbox::MITIGATION_STRICT_HANDLE_CHECKS; - - result = mPolicy->SetDelayedProcessMitigations(mitigations); - ret = ret && (sandbox::SBOX_ALL_OK == result); - - // The following is required for the Java plugin. - result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, - sandbox::TargetPolicy::FILES_ALLOW_ANY, - L"\\??\\pipe\\jpi2_pid*_pipe*"); - ret = ret && (sandbox::SBOX_ALL_OK == result); + sandbox::JobLevel jobLevel; + sandbox::TokenLevel accessTokenLevel; + sandbox::IntegrityLevel initialIntegrityLevel; + sandbox::IntegrityLevel delayedIntegrityLevel; + if (aSandboxLevel > 2) { + jobLevel = sandbox::JOB_UNPROTECTED; + accessTokenLevel = sandbox::USER_LIMITED; + initialIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW; + delayedIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW; + } else if (aSandboxLevel == 2) { + jobLevel = sandbox::JOB_UNPROTECTED; + accessTokenLevel = sandbox::USER_INTERACTIVE; + initialIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW; + delayedIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW; } else { - result = mPolicy->SetJobLevel(sandbox::JOB_NONE, - 0 /* ui_exceptions */); - ret = (sandbox::SBOX_ALL_OK == result); - - result = mPolicy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS, - sandbox::USER_NON_ADMIN); - ret = ret && (sandbox::SBOX_ALL_OK == result); + jobLevel = sandbox::JOB_NONE; + accessTokenLevel = sandbox::USER_NON_ADMIN; + initialIntegrityLevel = sandbox::INTEGRITY_LEVEL_MEDIUM; + delayedIntegrityLevel = sandbox::INTEGRITY_LEVEL_MEDIUM; } - result = mPolicy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_MEDIUM); + sandbox::ResultCode result = mPolicy->SetJobLevel(jobLevel, + 0 /* ui_exceptions */); + bool ret = (sandbox::SBOX_ALL_OK == result); + + result = mPolicy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS, + accessTokenLevel); + ret = ret && (sandbox::SBOX_ALL_OK == result); + + result = mPolicy->SetIntegrityLevel(initialIntegrityLevel); + ret = ret && (sandbox::SBOX_ALL_OK == result); + result = mPolicy->SetDelayedIntegrityLevel(delayedIntegrityLevel); + ret = ret && (sandbox::SBOX_ALL_OK == result); + + sandbox::MitigationFlags mitigations = + sandbox::MITIGATION_BOTTOM_UP_ASLR | + sandbox::MITIGATION_HEAP_TERMINATE | + sandbox::MITIGATION_SEHOP | + sandbox::MITIGATION_DEP_NO_ATL_THUNK | + sandbox::MITIGATION_DEP; + + result = mPolicy->SetProcessMitigations(mitigations); + ret = ret && (sandbox::SBOX_ALL_OK == result); + + mitigations = + sandbox::MITIGATION_STRICT_HANDLE_CHECKS; + + result = mPolicy->SetDelayedProcessMitigations(mitigations); ret = ret && (sandbox::SBOX_ALL_OK == result); // Add the policy for the client side of a pipe. It is just a file @@ -224,12 +222,24 @@ SandboxBroker::SetSecurityLevelForPluginProcess(int32_t aSandboxLevel) ret = ret && (sandbox::SBOX_ALL_OK == result); // The NPAPI process needs to be able to duplicate shared memory to the - // content process, which are Section type handles. + // content process and broker process, which are Section type handles. + // Content and broker are for e10s and non-e10s cases. result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES, sandbox::TargetPolicy::HANDLES_DUP_ANY, L"Section"); ret = ret && (sandbox::SBOX_ALL_OK == result); + result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES, + sandbox::TargetPolicy::HANDLES_DUP_BROKER, + L"Section"); + ret = ret && (sandbox::SBOX_ALL_OK == result); + + // The following is required for the Java plugin. + result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, + sandbox::TargetPolicy::FILES_ALLOW_ANY, + L"\\??\\pipe\\jpi2_pid*_pipe*"); + ret = ret && (sandbox::SBOX_ALL_OK == result); + return ret; }