Backed out 2 changesets (bug 1744460) for causing build bustages at RLBoxSandboxPool.cpp. CLOSED TREE

Backed out changeset 582101d582a0 (bug 1744460)
Backed out changeset dba7b7c19b2f (bug 1744460)
This commit is contained in:
Butkovits Atila 2021-12-08 21:57:58 +02:00
parent f7ab15352a
commit 6ffe112d27
12 changed files with 94 additions and 156 deletions

View File

@ -9,8 +9,8 @@ origin:
description: rlbox integration for the wasm2c sandboxed code
url: https://github.com/PLSysSec/rlbox_wasm2c_sandbox
release: commit 54e8469095e7929c66aeecdc26f23f502b986218 (2021-12-08T08:12:13Z).
revision: 54e8469095e7929c66aeecdc26f23f502b986218
release: commit 287fca460d8df2673f16d834cca2d240caf28417 (2021-11-19T04:33:46Z).
revision: 287fca460d8df2673f16d834cca2d240caf28417
license: MIT
license-file: LICENSE
@ -34,4 +34,3 @@ vendoring:
- LibrarySandbox.md
- README.md

View File

@ -10,7 +10,6 @@
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/RLBoxUtils.h"
#include "mozilla/ScopeExit.h"
#include "opentype-sanitiser.h" // For ots_ntohl
using namespace rlbox;
using namespace mozilla;
@ -49,19 +48,19 @@ tainted_woff2<BrotliDecoderResult> RLBoxBrotliDecoderDecompressCallback(
return res;
}
UniquePtr<RLBoxSandboxDataBase> RLBoxWOFF2SandboxPool::CreateSandboxData(uint64_t aSize) {
UniquePtr<RLBoxSandboxDataBase> RLBoxWOFF2SandboxPool::CreateSandboxData() {
// Create woff2 sandbox
auto sandbox = MakeUnique<rlbox_sandbox_woff2>();
#if defined(MOZ_WASM_SANDBOXING_WOFF2)
bool createOK = sandbox->create_sandbox(/* infallible = */ false, aSize);
#ifdef MOZ_WASM_SANDBOXING_WOFF2
bool createOK = sandbox->create_sandbox(/* infallible = */ false);
#else
bool createOK = sandbox->create_sandbox();
#endif
NS_ENSURE_TRUE(createOK, nullptr);
UniquePtr<RLBoxWOFF2SandboxData> sbxData =
MakeUnique<RLBoxWOFF2SandboxData>(aSize, std::move(sandbox));
MakeUnique<RLBoxWOFF2SandboxData>(std::move(sandbox));
// Register brotli callback
sbxData->mDecompressCallback = sbxData->Sandbox()->register_callback(
@ -80,10 +79,9 @@ void RLBoxWOFF2SandboxPool::Initalize(size_t aDelaySeconds) {
ClearOnShutdown(&RLBoxWOFF2SandboxPool::sSingleton);
}
RLBoxWOFF2SandboxData::RLBoxWOFF2SandboxData(uint64_t aSize,
RLBoxWOFF2SandboxData::RLBoxWOFF2SandboxData(
mozilla::UniquePtr<rlbox_sandbox_woff2> aSandbox)
: mozilla::RLBoxSandboxDataBase(aSize),
mSandbox(std::move(aSandbox)) {
: mSandbox(std::move(aSandbox)) {
MOZ_COUNT_CTOR(RLBoxWOFF2SandboxData);
}
@ -94,45 +92,6 @@ RLBoxWOFF2SandboxData::~RLBoxWOFF2SandboxData() {
MOZ_COUNT_DTOR(RLBoxWOFF2SandboxData);
}
static bool Woff2SizeValidator(size_t aLength, size_t aSize) {
if (aSize < aLength) {
NS_WARNING("Size of decompressed WOFF 2.0 is less than compressed size");
return false;
} else if (aSize == 0) {
NS_WARNING("Size of decompressed WOFF 2.0 is set to 0");
return false;
} else if (aSize > OTS_MAX_DECOMPRESSED_FILE_SIZE) {
NS_WARNING(
nsPrintfCString("Size of decompressed WOFF 2.0 font exceeds %gMB",
OTS_MAX_DECOMPRESSED_FILE_SIZE / (1024.0 * 1024.0))
.get());
return false;
}
return true;
}
// Code replicated from modules/woff2/src/woff2_dec.cc
// This is used both to compute the expected size of the Woff2 RLBox sandbox
// as well as internally by WOFF2 as a performance hint
static uint32_t ComputeWOFF2FinalSize(const uint8_t* aData, size_t aLength) {
// Expected size is stored as a 4 byte value starting from the 17th byte
if (aLength < 20) {
return 0;
}
uint32_t decompressedSize = 0;
const void* location = &(aData[16]);
std::memcpy(&decompressedSize, location, sizeof(decompressedSize));
decompressedSize = ots_ntohl(decompressedSize);
if(!Woff2SizeValidator(aLength, decompressedSize)) {
return 0;
}
return decompressedSize;
}
template <typename T>
using TransferBufferToWOFF2 =
mozilla::RLBoxTransferBufferToSandbox<T, rlbox_woff2_sandbox_type>;
@ -152,15 +111,7 @@ bool RLBoxProcessWOFF2(ots::FontFile* aHeader, ots::OTSStream* aOutput,
// index (7).
NS_ENSURE_TRUE(aLength >= 8, false);
uint32_t expectedSize = ComputeWOFF2FinalSize(aData, aLength);
NS_ENSURE_TRUE(expectedSize > 0, false);
// The sandbox should have space for the input, output and misc allocations
// To account for misc allocations, we'll set the sandbox size to
// input + output + 33% extra
const uint64_t expectedSandboxSize = static_cast<uint64_t>(1.33 * (aLength + expectedSize));
auto sandboxPoolData = RLBoxWOFF2SandboxPool::sSingleton->PopOrCreate(expectedSandboxSize);
auto sandboxPoolData = RLBoxWOFF2SandboxPool::sSingleton->PopOrCreate();
NS_ENSURE_TRUE(sandboxPoolData, false);
const auto* sandboxData =
@ -175,6 +126,38 @@ bool RLBoxProcessWOFF2(ots::FontFile* aHeader, ots::OTSStream* aOutput,
sandbox, reinterpret_cast<const char*>(aData), aLength);
NS_ENSURE_TRUE(*data, false);
// Validator for the decompression size.
// Returns the size and sets validateOK to true if size is valid (and false
// otherwise).
bool validateOK = false;
auto sizeValidator = [aLength, &validateOK](auto size) {
validateOK = false;
if (size < aLength) {
NS_WARNING("Size of decompressed WOFF 2.0 is less than compressed size");
} else if (size == 0) {
NS_WARNING("Size of decompressed WOFF 2.0 is set to 0");
} else if (size > OTS_MAX_DECOMPRESSED_FILE_SIZE) {
NS_WARNING(
nsPrintfCString("Size of decompressed WOFF 2.0 font exceeds %gMB",
OTS_MAX_DECOMPRESSED_FILE_SIZE / (1024.0 * 1024.0))
.get());
} else {
validateOK = true;
}
return size;
};
// Get the (estimated) decompression size and validate it.
unsigned long decompressedSize =
sandbox
->invoke_sandbox_function(RLBoxComputeWOFF2FinalSize, *data, aLength)
.copy_and_verify(sizeValidator);
if (NS_WARN_IF(!validateOK)) {
return false;
}
// Perform the actual conversion to TTF.
auto sizep = WOFF2Alloc<unsigned long>(sandbox);
@ -184,7 +167,7 @@ bool RLBoxProcessWOFF2(ots::FontFile* aHeader, ots::OTSStream* aOutput,
if (!sandbox
->invoke_sandbox_function(RLBoxConvertWOFF2ToTTF, *data, aLength,
expectedSize, sizep.get(),
decompressedSize, sizep.get(),
bufOwnerString.get(), bufp.get())
.unverified_safe_because(
"The ProcessTT* functions validate the decompressed data.")) {
@ -199,28 +182,26 @@ bool RLBoxProcessWOFF2(ots::FontFile* aHeader, ots::OTSStream* aOutput,
// Get the actual decompression size and validate it.
// We need to validate the size again. RLBoxConvertWOFF2ToTTF works even if
// the computed size (with ComputeWOFF2FinalSize) is wrong, so we can't
// trust the expectedSize to be the same as size sizep.
bool validateOK = false;
unsigned long actualSize = (*sizep.get()).copy_and_verify([&](unsigned long val){
validateOK = Woff2SizeValidator(aLength, val);
return val;
});
// the computed size (with RLBoxComputeWOFF2FinalSize) is wrong, so we can't
// trust the decompressedSize to be the same as size sizep.
unsigned long size = (*sizep.get()).copy_and_verify(sizeValidator);
NS_ENSURE_TRUE(validateOK, false);
if (NS_WARN_IF(!validateOK)) {
return false;
}
const uint8_t* decompressed = reinterpret_cast<const uint8_t*>(
(*bufp.get())
.unverified_safe_pointer_because(
actualSize, "Only care that the buffer is within sandbox boundary."));
size, "Only care that the buffer is within sandbox boundary."));
// Since ProcessTT* memcpy from the buffer, make sure it's not null.
NS_ENSURE_TRUE(decompressed, false);
if (aData[4] == 't' && aData[5] == 't' && aData[6] == 'c' &&
aData[7] == 'f') {
return aProcessTTC(aHeader, aOutput, decompressed, actualSize, aIndex);
return aProcessTTC(aHeader, aOutput, decompressed, size, aIndex);
}
ots::Font font(aHeader);
return aProcessTTF(aHeader, &font, aOutput, decompressed, actualSize, 0);
return aProcessTTF(aHeader, &font, aOutput, decompressed, size, 0);
}

View File

@ -33,7 +33,7 @@ class RLBoxWOFF2SandboxData : public mozilla::RLBoxSandboxDataBase {
friend class RLBoxWOFF2SandboxPool;
public:
RLBoxWOFF2SandboxData(uint64_t aSize, mozilla::UniquePtr<rlbox_sandbox_woff2> aSandbox);
RLBoxWOFF2SandboxData(mozilla::UniquePtr<rlbox_sandbox_woff2> aSandbox);
~RLBoxWOFF2SandboxData();
rlbox_sandbox_woff2* Sandbox() const { return mSandbox.get(); }

View File

@ -29,7 +29,7 @@ class RLBoxWOFF2SandboxPool : public mozilla::RLBoxSandboxPool {
static void Initalize(size_t aDelaySeconds = 10);
protected:
mozilla::UniquePtr<mozilla::RLBoxSandboxDataBase> CreateSandboxData(uint64_t aSize)
mozilla::UniquePtr<mozilla::RLBoxSandboxDataBase> CreateSandboxData()
override;
~RLBoxWOFF2SandboxPool() = default;
};

View File

@ -32,6 +32,12 @@ void RLBoxDeleteWOFF2String(void** aStr) {
delete buf;
}
unsigned long RLBoxComputeWOFF2FinalSize(const char* aData,
unsigned long aLength) {
return woff2::ComputeWOFF2FinalSize(reinterpret_cast<const uint8_t*>(aData),
aLength);
}
BrotliDecompressCallback* sRLBoxBrotliDecompressCallback = nullptr;
void RegisterWOFF2Callback(BrotliDecompressCallback* aCallback) {

View File

@ -15,6 +15,8 @@ extern "C" {
// we're using unsigned long instead of size_t and char instead of uint8_t.
// Since RLBox doesn't support C++ APIs, we expose C wrappers for the WOFF2.
unsigned long RLBoxComputeWOFF2FinalSize(const char* aData,
unsigned long aLength);
bool RLBoxConvertWOFF2ToTTF(const char* aData, unsigned long aLength,
unsigned long aDecompressedSize,
unsigned long* aResultSize, void** aResultOwningStr,

View File

@ -1342,12 +1342,12 @@ nsExpatDriver::ConsumeToken(nsScanner& aScanner, bool& aFlushTokens) {
}
mozilla::UniquePtr<mozilla::RLBoxSandboxDataBase>
RLBoxExpatSandboxPool::CreateSandboxData(uint64_t aSize) {
RLBoxExpatSandboxPool::CreateSandboxData() {
// Create expat sandbox
auto sandbox = mozilla::MakeUnique<rlbox_sandbox_expat>();
#ifdef MOZ_WASM_SANDBOXING_EXPAT
bool create_ok = sandbox->create_sandbox(/* infallible = */ false, aSize);
bool create_ok = sandbox->create_sandbox(/* infallible = */ false);
#else
bool create_ok = sandbox->create_sandbox();
#endif
@ -1355,7 +1355,7 @@ RLBoxExpatSandboxPool::CreateSandboxData(uint64_t aSize) {
NS_ENSURE_TRUE(create_ok, nullptr);
mozilla::UniquePtr<RLBoxExpatSandboxData> sbxData =
mozilla::MakeUnique<RLBoxExpatSandboxData>(aSize);
mozilla::MakeUnique<RLBoxExpatSandboxData>();
// Register callbacks common to both system and non-system principals
sbxData->mHandleXMLDeclaration =

View File

@ -154,10 +154,7 @@ class RLBoxExpatSandboxData : public mozilla::RLBoxSandboxDataBase {
friend class nsExpatDriver;
public:
explicit RLBoxExpatSandboxData(uint64_t aSize)
: mozilla::RLBoxSandboxDataBase(aSize) {
MOZ_COUNT_CTOR(RLBoxExpatSandboxData);
}
MOZ_COUNTED_DEFAULT_CTOR(RLBoxExpatSandboxData);
~RLBoxExpatSandboxData();
rlbox_sandbox_expat* Sandbox() const { return mSandbox.get(); }
// After getting a sandbox from the pool we need to register the

View File

@ -19,8 +19,8 @@ class RLBoxExpatSandboxPool : public mozilla::RLBoxSandboxPool {
static void Initialize(size_t aDelaySeconds = 10);
protected:
mozilla::UniquePtr<mozilla::RLBoxSandboxDataBase> CreateSandboxData(
uint64_t aSize) override;
mozilla::UniquePtr<mozilla::RLBoxSandboxDataBase> CreateSandboxData()
override;
~RLBoxExpatSandboxPool() = default;
};

View File

@ -417,35 +417,6 @@ __attribute__((weak))
return power;
}
public:
#define WASM_PAGE_SIZE 65536
#define WASM_HEAP_MAX_ALLOWED_PAGES 65536
#define WASM_MAX_HEAP (static_cast<uint64_t>(1) << 32)
static uint64_t rlbox_wasm2c_get_adjusted_heap_size(uint64_t heap_size)
{
if (heap_size == 0){
return 0;
}
if(heap_size <= WASM_PAGE_SIZE) {
return WASM_PAGE_SIZE;
} else if (heap_size >= WASM_MAX_HEAP) {
return WASM_MAX_HEAP;
}
return next_power_of_two(static_cast<uint32_t>(heap_size));
}
static uint64_t rlbox_wasm2c_get_heap_page_count(uint64_t heap_size)
{
const uint64_t pages = heap_size / WASM_PAGE_SIZE;
return pages;
}
#undef WASM_MAX_HEAP
#undef WASM_HEAP_MAX_ALLOWED_PAGES
#undef WASM_PAGE_SIZE
protected:
#ifndef RLBOX_USE_STATIC_CALLS
@ -553,9 +524,23 @@ protected:
sandbox_info.wasm_rt_sys_init();
});
override_max_heap_size = rlbox_wasm2c_get_adjusted_heap_size(override_max_heap_size);
const uint64_t override_max_wasm_pages = rlbox_wasm2c_get_heap_page_count(override_max_heap_size);
#define WASM_PAGE_SIZE 65536
#define WASM_HEAP_MAX_ALLOWED_PAGES 65536
#define WASM_MAX_HEAP (static_cast<uint64_t>(1) << 32)
if (override_max_heap_size != 0){
if(override_max_heap_size < WASM_PAGE_SIZE) {
override_max_heap_size = WASM_PAGE_SIZE;
} else if (override_max_heap_size > WASM_MAX_HEAP) {
override_max_heap_size = WASM_MAX_HEAP;
} else {
override_max_heap_size = next_power_of_two(override_max_heap_size);
}
}
const uint64_t override_max_wasm_pages = override_max_heap_size / WASM_PAGE_SIZE;
FALLIBLE_DYNAMIC_CHECK(infallible, override_max_wasm_pages <= 65536, "Wasm allows a max heap size of 4GB");
#undef WASM_MAX_HEAP
#undef WASM_HEAP_MAX_ALLOWED_PAGES
#undef WASM_PAGE_SIZE
sandbox = sandbox_info.create_wasm2c_sandbox(static_cast<uint32_t>(override_max_wasm_pages));
FALLIBLE_DYNAMIC_CHECK(infallible, sandbox != nullptr, "Sandbox could not be created");

View File

@ -8,8 +8,6 @@
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/RLBoxSandboxPool.h"
#include "mozilla/rlbox/rlbox_config.h"
#include "mozilla/rlbox/rlbox_wasm2c_sandbox.hpp"
using namespace mozilla;
@ -65,44 +63,18 @@ void RLBoxSandboxPool::Push(UniquePtr<RLBoxSandboxDataBase> sbxData) {
}
}
UniquePtr<RLBoxSandboxPoolData> RLBoxSandboxPool::PopOrCreate(
uint64_t aMinSize) {
UniquePtr<RLBoxSandboxPoolData> RLBoxSandboxPool::PopOrCreate() {
MutexAutoLock lock(mMutex);
UniquePtr<RLBoxSandboxDataBase> sbxData;
if (!mPool.IsEmpty()) {
const int64_t lastIndex = ReleaseAssertedCast<int64_t>(mPool.Length()) - 1;
for (int64_t i = lastIndex; i >= 0; i--) {
if (mPool[i]->mSize >= aMinSize) {
sbxData = std::move(mPool[i]);
mPool.RemoveElementAt(i);
// If we reuse a sandbox from the pool, reset the timer to clear the
// pool
CancelTimer();
if (!mPool.IsEmpty()) {
StartTimer();
}
break;
}
sbxData = mPool.PopLastElement();
CancelTimer();
if (!mPool.IsEmpty()) {
StartTimer();
}
}
if (!sbxData) {
// RLBox's wasm sandboxes have a limited platform dependent capacity. We
// track this capacity in this pool. Note the noop sandboxes have no
// capacity limit but this design assumes that all sandboxes use the wasm
// sandbox limit.
const uint64_t defaultCapacityForSandbox =
wasm_rt_get_default_max_linear_memory_size();
const uint64_t minSandboxCapacity =
std::max(aMinSize, defaultCapacityForSandbox);
const uint64_t rlboxAdjustedCapacity =
rlbox::rlbox_wasm2c_sandbox::rlbox_wasm2c_get_adjusted_heap_size(
minSandboxCapacity);
sbxData = CreateSandboxData(rlboxAdjustedCapacity);
} else {
sbxData = CreateSandboxData();
NS_ENSURE_TRUE(sbxData, nullptr);
}

View File

@ -44,15 +44,13 @@ class RLBoxSandboxPool : public nsITimerCallback, public nsINamed {
mMutex("RLBoxSandboxPool::mMutex"){};
void Push(UniquePtr<RLBoxSandboxDataBase> sbx);
// PopOrCreate returns a sandbox from the pool if the pool is not empty and
// 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. The parameter aMinSize is the minimum size of
// the sandbox memory.
UniquePtr<RLBoxSandboxPoolData> PopOrCreate(uint64_t aMinSize = 0);
// function returns a nullptr.
UniquePtr<RLBoxSandboxPoolData> PopOrCreate();
protected:
// CreateSandboxData takes a parameter which is the size of the sandbox memory
virtual UniquePtr<RLBoxSandboxDataBase> CreateSandboxData(uint64_t aSize) = 0;
virtual UniquePtr<RLBoxSandboxDataBase> CreateSandboxData() = 0;
virtual ~RLBoxSandboxPool() = default;
private:
@ -70,8 +68,6 @@ class RLBoxSandboxPool : public nsITimerCallback, public nsINamed {
// (e.g., callbacks).
class RLBoxSandboxDataBase {
public:
const uint64_t mSize;
explicit RLBoxSandboxDataBase(uint64_t aSize) : mSize(aSize) {}
virtual ~RLBoxSandboxDataBase() = default;
};