зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1740399 - Ensure hunspell fails gracefully on rlbox sandbox OOM r=bholley
Differential Revision: https://phabricator.services.mozilla.com/D130827
This commit is contained in:
Родитель
dc8d909659
Коммит
084c4704b8
|
@ -37,11 +37,14 @@ static tainted_hunspell<char*> allocStrInSandbox(
|
|||
return t_str;
|
||||
}
|
||||
|
||||
RLBoxHunspell::RLBoxHunspell(const nsAutoCString& affpath,
|
||||
const nsAutoCString& dpath)
|
||||
: mHandle(nullptr) {
|
||||
/* static */
|
||||
RLBoxHunspell* RLBoxHunspell::Create(const nsAutoCString& affpath,
|
||||
const nsAutoCString& dpath) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
|
||||
|
||||
mozilla::UniquePtr<rlbox_sandbox_hunspell, RLBoxDeleter> sandbox(
|
||||
new rlbox_sandbox_hunspell());
|
||||
|
||||
#if defined(MOZ_WASM_SANDBOXING_HUNSPELL) && !defined(HAVE_64BIT_BUILD)
|
||||
// By default, the rlbox sandbox size is smaller on 32-bit builds than the max
|
||||
// 4GB We may need to ask for a larger sandbox size for hunspell to spellcheck
|
||||
|
@ -65,16 +68,20 @@ RLBoxHunspell::RLBoxHunspell(const nsAutoCString& affpath,
|
|||
|
||||
// If we expect a higher memory usage, override the defaults
|
||||
// else stick with the defaults for the sandbox
|
||||
if (expectedMaxMemory > defaultMaxSizeForSandbox) {
|
||||
mSandbox.create_sandbox(true /* abort on creation failure */,
|
||||
expectedMaxMemory);
|
||||
} else {
|
||||
mSandbox.create_sandbox();
|
||||
}
|
||||
const uint64_t selectedMaxMemory =
|
||||
std::max(expectedMaxMemory, defaultMaxSizeForSandbox);
|
||||
|
||||
bool success = sandbox->create_sandbox(/* shouldAbortOnFailure = */ false,
|
||||
selectedMaxMemory);
|
||||
#elif defined(MOZ_WASM_SANDBOXING_HUNSPELL)
|
||||
bool success = sandbox->create_sandbox(/* shouldAbortOnFailure = */ false);
|
||||
#else
|
||||
mSandbox.create_sandbox();
|
||||
sandbox->create_sandbox();
|
||||
const bool success = true;
|
||||
#endif
|
||||
|
||||
NS_ENSURE_TRUE(success, nullptr);
|
||||
|
||||
// Add the aff and dict files to allow list
|
||||
if (!affpath.IsEmpty()) {
|
||||
mozHunspellCallbacks::AllowFile(affpath);
|
||||
|
@ -83,46 +90,53 @@ RLBoxHunspell::RLBoxHunspell(const nsAutoCString& affpath,
|
|||
mozHunspellCallbacks::AllowFile(dpath);
|
||||
}
|
||||
|
||||
return new RLBoxHunspell(std::move(sandbox), affpath, dpath);
|
||||
}
|
||||
|
||||
RLBoxHunspell::RLBoxHunspell(
|
||||
mozilla::UniquePtr<rlbox_sandbox_hunspell, RLBoxDeleter> aSandbox,
|
||||
const nsAutoCString& affpath, const nsAutoCString& dpath)
|
||||
: mSandbox(std::move(aSandbox)), mHandle(nullptr) {
|
||||
// Register callbacks
|
||||
mCreateFilemgr =
|
||||
mSandbox.register_callback(mozHunspellCallbacks::CreateFilemgr);
|
||||
mGetLine = mSandbox.register_callback(mozHunspellCallbacks::GetLine);
|
||||
mGetLineNum = mSandbox.register_callback(mozHunspellCallbacks::GetLineNum);
|
||||
mSandbox->register_callback(mozHunspellCallbacks::CreateFilemgr);
|
||||
mGetLine = mSandbox->register_callback(mozHunspellCallbacks::GetLine);
|
||||
mGetLineNum = mSandbox->register_callback(mozHunspellCallbacks::GetLineNum);
|
||||
mDestructFilemgr =
|
||||
mSandbox.register_callback(mozHunspellCallbacks::DestructFilemgr);
|
||||
mSandbox->register_callback(mozHunspellCallbacks::DestructFilemgr);
|
||||
mHunspellToUpperCase =
|
||||
mSandbox.register_callback(mozHunspellCallbacks::ToUpperCase);
|
||||
mSandbox->register_callback(mozHunspellCallbacks::ToUpperCase);
|
||||
mHunspellToLowerCase =
|
||||
mSandbox.register_callback(mozHunspellCallbacks::ToLowerCase);
|
||||
mSandbox->register_callback(mozHunspellCallbacks::ToLowerCase);
|
||||
mHunspellGetCurrentCS =
|
||||
mSandbox.register_callback(mozHunspellCallbacks::GetCurrentCS);
|
||||
mSandbox->register_callback(mozHunspellCallbacks::GetCurrentCS);
|
||||
|
||||
mSandbox.invoke_sandbox_function(RegisterHunspellCallbacks, mCreateFilemgr,
|
||||
mGetLine, mGetLineNum, mDestructFilemgr,
|
||||
mHunspellToUpperCase, mHunspellToLowerCase,
|
||||
mHunspellGetCurrentCS);
|
||||
mSandbox->invoke_sandbox_function(RegisterHunspellCallbacks, mCreateFilemgr,
|
||||
mGetLine, mGetLineNum, mDestructFilemgr,
|
||||
mHunspellToUpperCase, mHunspellToLowerCase,
|
||||
mHunspellGetCurrentCS);
|
||||
|
||||
// Copy the affpath and dpath into the sandbox
|
||||
// These allocations should definitely succeed as these are first allocations
|
||||
// inside the sandbox.
|
||||
tainted_hunspell<char*> t_affpath = allocStrInSandbox(mSandbox, affpath);
|
||||
tainted_hunspell<char*> t_affpath = allocStrInSandbox(*mSandbox, affpath);
|
||||
MOZ_RELEASE_ASSERT(t_affpath);
|
||||
|
||||
tainted_hunspell<char*> t_dpath = allocStrInSandbox(mSandbox, dpath);
|
||||
tainted_hunspell<char*> t_dpath = allocStrInSandbox(*mSandbox, dpath);
|
||||
MOZ_RELEASE_ASSERT(t_dpath);
|
||||
|
||||
// Create handle
|
||||
mHandle = mSandbox.invoke_sandbox_function(
|
||||
mHandle = mSandbox->invoke_sandbox_function(
|
||||
Hunspell_create, rlbox::sandbox_const_cast<const char*>(t_affpath),
|
||||
rlbox::sandbox_const_cast<const char*>(t_dpath));
|
||||
MOZ_RELEASE_ASSERT(mHandle);
|
||||
|
||||
mSandbox.free_in_sandbox(t_dpath);
|
||||
mSandbox.free_in_sandbox(t_affpath);
|
||||
mSandbox->free_in_sandbox(t_dpath);
|
||||
mSandbox->free_in_sandbox(t_affpath);
|
||||
|
||||
// Get dictionary encoding
|
||||
tainted_hunspell<char*> t_enc =
|
||||
mSandbox.invoke_sandbox_function(Hunspell_get_dic_encoding, mHandle);
|
||||
mSandbox->invoke_sandbox_function(Hunspell_get_dic_encoding, mHandle);
|
||||
t_enc.copy_and_verify_string([&](std::unique_ptr<char[]> enc) {
|
||||
size_t len = std::strlen(enc.get());
|
||||
mDicEncoding = std::string(enc.get(), len);
|
||||
|
@ -132,7 +146,7 @@ RLBoxHunspell::RLBoxHunspell(const nsAutoCString& affpath,
|
|||
RLBoxHunspell::~RLBoxHunspell() {
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
|
||||
// Call hunspell's destroy which frees mHandle
|
||||
mSandbox.invoke_sandbox_function(Hunspell_destroy, mHandle);
|
||||
mSandbox->invoke_sandbox_function(Hunspell_destroy, mHandle);
|
||||
mHandle = nullptr;
|
||||
|
||||
// Unregister callbacks
|
||||
|
@ -146,15 +160,12 @@ RLBoxHunspell::~RLBoxHunspell() {
|
|||
|
||||
// Clear any callback data and allow list
|
||||
mozHunspellCallbacks::Clear();
|
||||
|
||||
// Dstroy sandbox
|
||||
mSandbox.destroy_sandbox();
|
||||
}
|
||||
|
||||
int RLBoxHunspell::spell(const std::string& stdWord) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
|
||||
// Copy word into the sandbox
|
||||
tainted_hunspell<char*> t_word = allocStrInSandbox(mSandbox, stdWord);
|
||||
tainted_hunspell<char*> t_word = allocStrInSandbox(*mSandbox, stdWord);
|
||||
if (!t_word) {
|
||||
// Ran out of memory in the hunspell sandbox
|
||||
// Fail gracefully assuming the word is spelt correctly
|
||||
|
@ -164,11 +175,11 @@ int RLBoxHunspell::spell(const std::string& stdWord) {
|
|||
|
||||
// Check word
|
||||
int good = mSandbox
|
||||
.invoke_sandbox_function(
|
||||
->invoke_sandbox_function(
|
||||
Hunspell_spell, mHandle,
|
||||
rlbox::sandbox_const_cast<const char*>(t_word))
|
||||
.copy_and_verify([](int good) { return good; });
|
||||
mSandbox.free_in_sandbox(t_word);
|
||||
mSandbox->free_in_sandbox(t_word);
|
||||
return good;
|
||||
}
|
||||
|
||||
|
@ -181,16 +192,16 @@ const std::string& RLBoxHunspell::get_dict_encoding() const {
|
|||
std::vector<std::string> RLBoxHunspell::suggest(const std::string& stdWord) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
|
||||
// Copy word into the sandbox
|
||||
tainted_hunspell<char*> t_word = allocStrInSandbox(mSandbox, stdWord);
|
||||
tainted_hunspell<char*> t_word = allocStrInSandbox(*mSandbox, stdWord);
|
||||
if (!t_word) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// Allocate suggestion list in the sandbox
|
||||
tainted_hunspell<char***> t_slst = mSandbox.malloc_in_sandbox<char**>();
|
||||
tainted_hunspell<char***> t_slst = mSandbox->malloc_in_sandbox<char**>();
|
||||
if (!t_slst) {
|
||||
// Free the earlier allocation
|
||||
mSandbox.free_in_sandbox(t_word);
|
||||
mSandbox->free_in_sandbox(t_word);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -198,7 +209,7 @@ std::vector<std::string> RLBoxHunspell::suggest(const std::string& stdWord) {
|
|||
|
||||
// Get suggestions
|
||||
int nr = mSandbox
|
||||
.invoke_sandbox_function(
|
||||
->invoke_sandbox_function(
|
||||
Hunspell_suggest, mHandle, t_slst,
|
||||
rlbox::sandbox_const_cast<const char*>(t_word))
|
||||
.copy_and_verify([](int nr) {
|
||||
|
@ -220,15 +231,15 @@ std::vector<std::string> RLBoxHunspell::suggest(const std::string& stdWord) {
|
|||
t_sug.copy_and_verify_string(
|
||||
[&](std::string sug) { suggestions.push_back(std::move(sug)); });
|
||||
// free the suggestion string allocated by the sandboxed hunspell
|
||||
mSandbox.free_in_sandbox(t_sug);
|
||||
mSandbox->free_in_sandbox(t_sug);
|
||||
}
|
||||
}
|
||||
|
||||
// free the suggestion list allocated by the sandboxed hunspell
|
||||
mSandbox.free_in_sandbox(t_slst_ref);
|
||||
mSandbox->free_in_sandbox(t_slst_ref);
|
||||
}
|
||||
|
||||
mSandbox.free_in_sandbox(t_word);
|
||||
mSandbox.free_in_sandbox(t_slst);
|
||||
mSandbox->free_in_sandbox(t_word);
|
||||
mSandbox->free_in_sandbox(t_slst);
|
||||
return suggestions;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,9 @@
|
|||
|
||||
class RLBoxHunspell {
|
||||
public:
|
||||
RLBoxHunspell(const nsAutoCString& affpath, const nsAutoCString& dpath);
|
||||
static RLBoxHunspell* Create(const nsAutoCString& affpath,
|
||||
const nsAutoCString& dpath);
|
||||
|
||||
~RLBoxHunspell();
|
||||
|
||||
int spell(const std::string& stdWord);
|
||||
|
@ -38,7 +40,18 @@ class RLBoxHunspell {
|
|||
std::vector<std::string> suggest(const std::string& word);
|
||||
|
||||
private:
|
||||
rlbox_sandbox_hunspell mSandbox;
|
||||
struct RLBoxDeleter {
|
||||
void operator()(rlbox_sandbox_hunspell* sandbox) {
|
||||
sandbox->destroy_sandbox();
|
||||
delete sandbox;
|
||||
}
|
||||
};
|
||||
|
||||
RLBoxHunspell(
|
||||
mozilla::UniquePtr<rlbox_sandbox_hunspell, RLBoxDeleter> aSandbox,
|
||||
const nsAutoCString& affpath, const nsAutoCString& dpath);
|
||||
|
||||
mozilla::UniquePtr<rlbox_sandbox_hunspell, RLBoxDeleter> mSandbox;
|
||||
sandbox_callback_hunspell<hunspell_create_filemgr_t*> mCreateFilemgr;
|
||||
sandbox_callback_hunspell<hunspell_get_line_t*> mGetLine;
|
||||
sandbox_callback_hunspell<hunspell_get_line_num_t*> mGetLineNum;
|
||||
|
|
|
@ -188,7 +188,7 @@ mozHunspell::SetDictionary(const nsACString& aDictionary) {
|
|||
mDictionary = dict;
|
||||
mAffixFileName = affFileName;
|
||||
|
||||
mHunspell = new RLBoxHunspell(affFileName, dictFileName);
|
||||
mHunspell = RLBoxHunspell::Create(affFileName, dictFileName);
|
||||
if (!mHunspell) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
auto encoding =
|
||||
|
|
|
@ -78,8 +78,8 @@ class mozHunspellCallbacks {
|
|||
* Add filename to allow list.
|
||||
*/
|
||||
static void AllowFile(const nsCString& aFilename);
|
||||
friend RLBoxHunspell::RLBoxHunspell(const nsAutoCString& affpath,
|
||||
const nsAutoCString& dpath);
|
||||
friend RLBoxHunspell* RLBoxHunspell::Create(const nsAutoCString& affpath,
|
||||
const nsAutoCString& dpath);
|
||||
/**
|
||||
* Clear allow list and map of hunspell file managers.
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче