author | Deian Stefan <deian@cs.ucsd.edu> |
Fri, 12 Nov 2021 05:20:29 +0000 | |
changeset 599012 | 8fe04ef415915226cf80a1c904477154183c247a |
parent 599011 | b16763f1da6bcf31f964744c765c4af480ae551c |
child 599013 | b7e727dbc32044bbbb3dadfee2780dcea7419fa2 |
push id | 38973 |
push user | smolnar@mozilla.com |
push date | Fri, 12 Nov 2021 21:34:06 +0000 |
treeherder | mozilla-central@d2b5e7cc2dbb [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | bholley |
bugs | 1740624 |
milestone | 96.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
new file mode 100644 --- /dev/null +++ b/security/rlbox/include/RLBoxSandboxPool.h @@ -0,0 +1,100 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef SECURITY_RLBOX_SANDBOX_POOL_H_ +#define SECURITY_RLBOX_SANDBOX_POOL_H_ + +#include "nsCOMPtr.h" +#include "nsITimer.h" +#include "nsTArray.h" + +#include "mozilla/Mutex.h" +#include "mozilla/rlbox/rlbox_types.hpp" + +namespace mozilla { + +class RLBoxSandboxDataBase; +class RLBoxSandboxPoolData; + +// The RLBoxSandboxPool class is used to manage a pool of sandboxes that are +// reused -- to save sandbox creation time and memory -- and automatically +// destroyed when no longer in used. The sandbox pool is threadsafe and can be +// used to share unused sandboxes across a thread pool. +// +// Each sandbox pool manages a particular kind of sandbox (e.g., expat +// sandboxes, woff2 sandboxes, etc.); this is largely because different +// sandboxes might have different callbacks and attacker assumptions. Hence, +// RLBoxSandboxPool is intended to be subclassed for the different kinds of +// sandbox pools. Each sandbox pool class needs to implement the +// CreateSandboxData() method, which returns a pointer to a RLBoxSandboxDataBase +// object. RLBoxSandboxDataBase itself should be subclassed to implement +// sandbox-specific details. +class RLBoxSandboxPool : public nsITimerCallback, public nsINamed { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSITIMERCALLBACK + NS_DECL_NSINAMED + + RLBoxSandboxPool(size_t aDelaySeconds = 10) + : mPool(), + mDelaySeconds(aDelaySeconds), + mMutex("RLBoxSandboxPool::mMutex"){}; + + void Push(UniquePtr<RLBoxSandboxDataBase> sbx); + // PopOrCreate() returns a sandbox from the pool if the pool is not empty and + // tries to mint a new one otherwise. If creating a new sandbox fails, the + // function returns a nullptr. + UniquePtr<RLBoxSandboxPoolData> PopOrCreate(); + + protected: + virtual UniquePtr<RLBoxSandboxDataBase> CreateSandboxData() = 0; + virtual ~RLBoxSandboxPool() = default; + + private: + void StartTimer(); + void CancelTimer(); + + nsTArray<UniquePtr<RLBoxSandboxDataBase>> mPool; + const size_t mDelaySeconds; + nsCOMPtr<nsITimer> mTimer; + mozilla::Mutex mMutex; +}; + +// The RLBoxSandboxDataBase class serves as the subclass for all sandbox data +// classes, which keep track of the RLBox sandbox and any relevant sandbox data +// (e.g., callbacks). +class RLBoxSandboxDataBase { + public: + virtual ~RLBoxSandboxDataBase() = default; +}; + +// This class is used wrap sandbox data objects (RLBoxSandboxDataBase) when they +// are popped from sandbox pools. The wrapper destructor pushes the sandbox back +// into the pool. +class RLBoxSandboxPoolData { + public: + RLBoxSandboxPoolData(UniquePtr<RLBoxSandboxDataBase> aSbxData, + RefPtr<RLBoxSandboxPool> aPool) { + mSbxData = std::move(aSbxData); + mPool = aPool; + MOZ_COUNT_CTOR(RLBoxSandboxPoolData); + } + + const RLBoxSandboxDataBase* SandboxData() const { return mSbxData.get(); }; + + ~RLBoxSandboxPoolData() { + mPool->Push(std::move(mSbxData)); + MOZ_COUNT_DTOR(RLBoxSandboxPoolData); + }; + + private: + UniquePtr<RLBoxSandboxDataBase> mSbxData; + RefPtr<RLBoxSandboxPool> mPool; +}; + +} // namespace mozilla + +#endif
--- a/security/rlbox/moz.build +++ b/security/rlbox/moz.build @@ -5,20 +5,27 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. WASM_SOURCES += [ "/third_party/rlbox_wasm2c_sandbox/c_src/wasm2c_sandbox_wrapper.c", ] LOCAL_INCLUDES += ["/third_party/wasm2c/wasm2c/"] -EXPORTS += ["/third_party/wasm2c/wasm2c/wasm-rt.h"] +EXPORTS += [ + "/third_party/wasm2c/wasm2c/wasm-rt.h", +] + +EXPORTS.mozilla += [ + "/security/rlbox/include/RLBoxSandboxPool.h", +] SOURCES += [ "!rlbox.wasm.c", + "/security/rlbox/src/RLBoxSandboxPool.cpp", "/third_party/wasm2c/wasm2c/wasm-rt-impl.c", "/third_party/wasm2c/wasm2c/wasm-rt-os-unix.c", "/third_party/wasm2c/wasm2c/wasm-rt-os-win.c", "/third_party/wasm2c/wasm2c/wasm-rt-wasi.c", ] # Configure the wasm runtime to use a custom trap handler that calls MOZ_CRASH DEFINES["WASM_RT_CUSTOM_TRAP_HANDLER"] = "moz_wasm2c_trap_handler"
new file mode 100644 --- /dev/null +++ b/security/rlbox/src/RLBoxSandboxPool.cpp @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsThreadUtils.h" +#include "mozilla/DebugOnly.h" +#include "mozilla/RLBoxSandboxPool.h" + +using namespace mozilla; + +NS_IMPL_ISUPPORTS(RLBoxSandboxPool, nsITimerCallback, nsINamed) + +void RLBoxSandboxPool::StartTimer() { + mMutex.AssertCurrentThreadOwns(); + MOZ_ASSERT(!mTimer, "timer already initialized"); + DebugOnly<nsresult> rv = NS_NewTimerWithCallback( + getter_AddRefs(mTimer), this, mDelaySeconds * 1000, + nsITimer::TYPE_ONE_SHOT, GetMainThreadEventTarget()); + MOZ_ASSERT(NS_SUCCEEDED(rv), "failed to create timer"); +} + +void RLBoxSandboxPool::CancelTimer() { + mMutex.AssertCurrentThreadOwns(); + if (mTimer) { + mTimer->Cancel(); + mTimer = nullptr; + } +} + +NS_IMETHODIMP RLBoxSandboxPool::Notify(nsITimer* aTimer) { + MutexAutoLock lock(mMutex); + + mPool.Clear(); + mTimer = nullptr; + + return NS_OK; +} + +NS_IMETHODIMP RLBoxSandboxPool::GetName(nsACString& aName) { + aName.AssignLiteral("RLBoxSandboxPool"); + return NS_OK; +} + +void RLBoxSandboxPool::Push(UniquePtr<RLBoxSandboxDataBase> sbxData) { + MutexAutoLock lock(mMutex); + + mPool.AppendElement(std::move(sbxData)); + if (!mTimer) { + StartTimer(); + } +} + +UniquePtr<RLBoxSandboxPoolData> RLBoxSandboxPool::PopOrCreate() { + MutexAutoLock lock(mMutex); + + UniquePtr<RLBoxSandboxDataBase> sbxData; + if (!mPool.IsEmpty()) { + sbxData = mPool.PopLastElement(); + CancelTimer(); + if (!mPool.IsEmpty()) { + StartTimer(); + } + } else { + sbxData = CreateSandboxData(); + NS_ENSURE_TRUE(sbxData, nullptr); + } + + return MakeUnique<RLBoxSandboxPoolData>(std::move(sbxData), this); +}