Bug 1740624 - Add RLBox sandbox pool support r=bholley

Differential Revision: https://phabricator.services.mozilla.com/D130934
This commit is contained in:
Deian Stefan 2021-11-12 05:20:29 +00:00
Родитель 9b61a81283
Коммит 94453a2008
3 изменённых файлов: 179 добавлений и 1 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -10,10 +10,17 @@ WASM_SOURCES += [
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",

Просмотреть файл

@ -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);
}