forked from mirrors/gecko-dev
Backed out 4 changesets (bug 1733686, bug 1735935) for causing sandboxing crashes with the spellchecker (bug 1736171) . CLOSED TREE
Backed out changeset c981fa4490fe (bug 1735935) Backed out changeset a6fef4dc35c2 (bug 1733686) Backed out changeset d52827e69092 (bug 1733686) Backed out changeset 29ed3620fa91 (bug 1733686)
This commit is contained in:
parent
cc43051aeb
commit
66967cc3e6
16 changed files with 75 additions and 566 deletions
4
config/external/rlbox/rlbox_config.h
vendored
4
config/external/rlbox/rlbox_config.h
vendored
|
|
@ -6,8 +6,6 @@
|
|||
#ifndef RLBOX_CONFIG
|
||||
#define RLBOX_CONFIG
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
|
||||
// RLBox uses c++17's shared_locks by default, even for the noop_sandbox
|
||||
|
|
@ -33,8 +31,6 @@ struct rlbox_shared_lock {
|
|||
// performance
|
||||
#define RLBOX_SINGLE_THREADED_INVOCATIONS
|
||||
|
||||
#define RLBOX_CUSTOM_ABORT(msg) MOZ_CRASH_UNSAFE_PRINTF("RLBox crash: %s", msg)
|
||||
|
||||
// The MingW compiler does not correctly handle static thread_local inline
|
||||
// members. This toggles a workaround that allows the host application (firefox)
|
||||
// to provide TLS storage via functions. This can be removed if the MingW bug is
|
||||
|
|
|
|||
|
|
@ -19,9 +19,8 @@ static tainted_hunspell<char*> allocStrInSandbox(
|
|||
rlbox_sandbox_hunspell& aSandbox, const nsAutoCString& str) {
|
||||
size_t size = str.Length() + 1;
|
||||
tainted_hunspell<char*> t_str = aSandbox.malloc_in_sandbox<char>(size);
|
||||
if (t_str) {
|
||||
rlbox::memcpy(aSandbox, t_str, str.get(), size);
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(t_str);
|
||||
rlbox::memcpy(aSandbox, t_str, str.get(), size);
|
||||
return t_str;
|
||||
}
|
||||
|
||||
|
|
@ -30,9 +29,8 @@ static tainted_hunspell<char*> allocStrInSandbox(
|
|||
rlbox_sandbox_hunspell& aSandbox, const std::string& str) {
|
||||
size_t size = str.size() + 1;
|
||||
tainted_hunspell<char*> t_str = aSandbox.malloc_in_sandbox<char>(size);
|
||||
if (t_str) {
|
||||
rlbox::memcpy(aSandbox, t_str, str.c_str(), size);
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(t_str);
|
||||
rlbox::memcpy(aSandbox, t_str, str.c_str(), size);
|
||||
return t_str;
|
||||
}
|
||||
|
||||
|
|
@ -73,13 +71,8 @@ RLBoxHunspell::RLBoxHunspell(const nsAutoCString& affpath,
|
|||
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);
|
||||
MOZ_RELEASE_ASSERT(t_affpath);
|
||||
|
||||
tainted_hunspell<char*> t_dpath = allocStrInSandbox(mSandbox, dpath);
|
||||
MOZ_RELEASE_ASSERT(t_dpath);
|
||||
|
||||
// Create handle
|
||||
mHandle = mSandbox.invoke_sandbox_function(
|
||||
|
|
@ -123,12 +116,6 @@ RLBoxHunspell::~RLBoxHunspell() {
|
|||
int RLBoxHunspell::spell(const std::string& stdWord) {
|
||||
// Copy word into the sandbox
|
||||
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
|
||||
const int ok = 1;
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Check word
|
||||
int good = mSandbox
|
||||
|
|
@ -144,23 +131,12 @@ const std::string& RLBoxHunspell::get_dict_encoding() const {
|
|||
return mDicEncoding;
|
||||
}
|
||||
|
||||
// This function fails gracefully - if we run out of memory in the hunspell
|
||||
// sandbox, we return empty suggestion list
|
||||
std::vector<std::string> RLBoxHunspell::suggest(const std::string& stdWord) {
|
||||
// Copy word into the sandbox
|
||||
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**>();
|
||||
if (!t_slst) {
|
||||
// Free the earlier allocation
|
||||
mSandbox.free_in_sandbox(t_word);
|
||||
return {};
|
||||
}
|
||||
|
||||
*t_slst = nullptr;
|
||||
|
||||
// Get suggestions
|
||||
|
|
@ -173,26 +149,16 @@ std::vector<std::string> RLBoxHunspell::suggest(const std::string& stdWord) {
|
|||
return nr;
|
||||
});
|
||||
|
||||
tainted_hunspell<char**> t_slst_ref = *t_slst;
|
||||
|
||||
// Copy suggestions from sandbox
|
||||
std::vector<std::string> suggestions;
|
||||
if (nr > 0 && t_slst_ref != nullptr) {
|
||||
// Copy suggestions from sandbox
|
||||
suggestions.reserve(nr);
|
||||
|
||||
for (int i = 0; i < nr; i++) {
|
||||
tainted_hunspell<char*> t_sug = t_slst_ref[i];
|
||||
|
||||
if (t_sug) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// free the suggestion list allocated by the sandboxed hunspell
|
||||
mSandbox.free_in_sandbox(t_slst_ref);
|
||||
suggestions.reserve(nr);
|
||||
for (int i = 0; i < nr; i++) {
|
||||
tainted_hunspell<char*> t_sug = (*t_slst)[i];
|
||||
MOZ_RELEASE_ASSERT(t_sug);
|
||||
t_sug.copy_and_verify_string([&](std::unique_ptr<char[]> sug) {
|
||||
size_t len = std::strlen(sug.get());
|
||||
suggestions.push_back(std::string(sug.get(), len));
|
||||
});
|
||||
}
|
||||
|
||||
mSandbox.free_in_sandbox(t_word);
|
||||
|
|
|
|||
|
|
@ -146,19 +146,12 @@ tainted_hunspell<bool> mozHunspellCallbacks::GetLine(
|
|||
mozHunspellCallbacks::GetMozHunspellFileMgrHost(t_aFd);
|
||||
std::string line;
|
||||
bool ok = inst.GetLine(line);
|
||||
// If the getline fails, return a null which is "graceful" failure
|
||||
if (ok) {
|
||||
// Copy the line into the sandbox. This memory is eventually freed by
|
||||
// hunspell.
|
||||
// copy the line into the sandbox
|
||||
size_t size = line.size() + 1;
|
||||
tainted_hunspell<char*> t_line = aSandbox.malloc_in_sandbox<char>(size);
|
||||
|
||||
if (t_line == nullptr) {
|
||||
// If malloc fails, we should go to "graceful" failure path
|
||||
ok = false;
|
||||
} else {
|
||||
rlbox::memcpy(aSandbox, t_line, line.c_str(), size);
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(t_line);
|
||||
rlbox::memcpy(aSandbox, t_line, line.c_str(), size);
|
||||
*t_aLinePtr = t_line;
|
||||
} else {
|
||||
*t_aLinePtr = nullptr;
|
||||
|
|
|
|||
2
third_party/rlbox/README-mozilla
vendored
2
third_party/rlbox/README-mozilla
vendored
|
|
@ -1,7 +1,7 @@
|
|||
This directory contains the rlbox source from the upstream repo:
|
||||
https://github.com/PLSysSec/rlbox_sandboxing_api/
|
||||
|
||||
Current version: [commit a441977c8ff2da6626a3ff1a3cd2c6d0a9a9bed5]
|
||||
Current version: [commit fc796e549b3a48e89b9a8db28011dcad06494ba3]
|
||||
|
||||
UPDATING:
|
||||
|
||||
|
|
|
|||
66
third_party/rlbox/include/rlbox.hpp
vendored
66
third_party/rlbox/include/rlbox.hpp
vendored
|
|
@ -655,7 +655,7 @@ public:
|
|||
* @brief Copy a tainted string from sandbox and verify it.
|
||||
*
|
||||
* @param verifer Function used to verify the copied value.
|
||||
* @tparam T_Func the type of the verifier either ``T_Ret(*)(unique_ptr<char[]>)`` or ``T_Ret(*)(std::string)``
|
||||
* @tparam T_Func the type of the verifier ``T_Ret(*)(unique_ptr<char[]>)``
|
||||
* @return Whatever the verifier function returns.
|
||||
*/
|
||||
template<typename T_Func>
|
||||
|
|
@ -667,53 +667,23 @@ public:
|
|||
static_assert(std::is_same_v<char, T_CopyAndVerifyRangeEl>,
|
||||
"copy_and_verify_string only allows char*");
|
||||
|
||||
using T_VerifParam = detail::func_first_arg_t<T_Func>;
|
||||
|
||||
auto start = impl().get_raw_value();
|
||||
if_constexpr_named(cond1, std::is_same_v<T_VerifParam, std::unique_ptr<char[]>> || std::is_same_v<T_VerifParam, std::unique_ptr<const char[]>>) {
|
||||
if (start == nullptr) {
|
||||
return verifier(nullptr);
|
||||
}
|
||||
|
||||
// it is safe to run strlen on a tainted<string> as worst case, the string
|
||||
// does not have a null and we try to copy all the memory out of the sandbox
|
||||
// however, copy_and_verify_range ensures that we never copy memory outsider
|
||||
// the range
|
||||
auto str_len = std::strlen(start) + 1;
|
||||
std::unique_ptr<T_CopyAndVerifyRangeEl[]> target =
|
||||
copy_and_verify_range_helper(str_len);
|
||||
|
||||
// ensure the string has a trailing null
|
||||
target[str_len - 1] = '\0';
|
||||
|
||||
return verifier(std::move(target));
|
||||
} else if_constexpr_named (cond2, std::is_same_v<T_VerifParam, std::string>) {
|
||||
if (start == nullptr) {
|
||||
std::string param = "";
|
||||
return verifier(param);
|
||||
}
|
||||
|
||||
// it is safe to run strlen on a tainted<string> as worst case, the string
|
||||
// does not have a null and we try to copy all the memory out of the sandbox
|
||||
// however, copy_and_verify_range ensures that we never copy memory outsider
|
||||
// the range
|
||||
auto str_len = std::strlen(start) + 1;
|
||||
|
||||
const char* checked_start = (const char*) verify_range_helper(str_len);
|
||||
if (checked_start == nullptr) {
|
||||
std::string param = "";
|
||||
return verifier(param);
|
||||
}
|
||||
|
||||
std::string copy(checked_start, str_len - 1);
|
||||
return verifier(std::move(copy));
|
||||
} else {
|
||||
constexpr bool unknownCase = !(cond1 || cond2);
|
||||
rlbox_detail_static_fail_because(
|
||||
unknownCase,
|
||||
"copy_and_verify_string verifier parameter should either be unique_ptr<char[]>, unique_ptr<const char[]> or std::string"
|
||||
);
|
||||
if (start == nullptr) {
|
||||
return verifier(nullptr);
|
||||
}
|
||||
|
||||
// it is safe to run strlen on a tainted<string> as worst case, the string
|
||||
// does not have a null and we try to copy all the memory out of the sandbox
|
||||
// however, copy_and_verify_range ensures that we never copy memory outsider
|
||||
// the range
|
||||
auto str_len = std::strlen(start) + 1;
|
||||
std::unique_ptr<T_CopyAndVerifyRangeEl[]> target =
|
||||
copy_and_verify_range_helper(str_len);
|
||||
|
||||
// ensure the string has a trailing null
|
||||
target[str_len - 1] = '\0';
|
||||
|
||||
return verifier(std::move(target));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1182,7 +1152,6 @@ private:
|
|||
inline std::remove_cv_t<T_SandboxedType> get_raw_sandbox_value(
|
||||
rlbox_sandbox<T_Sbx>& sandbox) const noexcept
|
||||
{
|
||||
RLBOX_UNUSED(sandbox);
|
||||
return data;
|
||||
};
|
||||
|
||||
|
|
@ -1200,7 +1169,6 @@ private:
|
|||
inline std::remove_cv_t<T_SandboxedType> get_raw_sandbox_value(
|
||||
rlbox_sandbox<T_Sbx>& sandbox) noexcept
|
||||
{
|
||||
RLBOX_UNUSED(sandbox);
|
||||
rlbox_detail_forward_to_const(get_raw_sandbox_value,
|
||||
std::remove_cv_t<T_SandboxedType>);
|
||||
};
|
||||
|
|
@ -1293,7 +1261,7 @@ public:
|
|||
// is safe.
|
||||
auto func = val.get_raw_sandbox_value();
|
||||
using T_Cast = std::remove_volatile_t<T_SandboxedType>;
|
||||
get_sandbox_value_ref() = (T_Cast)func;
|
||||
get_sandbox_value_ref() = reinterpret_cast<T_Cast>(func);
|
||||
}
|
||||
}
|
||||
else if_constexpr_named(
|
||||
|
|
|
|||
13
third_party/rlbox/include/rlbox_app_pointer.hpp
vendored
13
third_party/rlbox/include/rlbox_app_pointer.hpp
vendored
|
|
@ -32,13 +32,13 @@ private:
|
|||
for (T_PointerTypeUnsigned i = counter; i < max_val; i++) {
|
||||
if (pointer_map.find(i) == pointer_map.end()) {
|
||||
counter = i + 1;
|
||||
return (T_PointerType)i;
|
||||
return reinterpret_cast<T_PointerType>(i);
|
||||
}
|
||||
}
|
||||
for (T_PointerTypeUnsigned i = min_val; i < counter; i++) {
|
||||
if (pointer_map.find(i) == pointer_map.end()) {
|
||||
counter = i + 1;
|
||||
return (T_PointerType)i;
|
||||
return reinterpret_cast<T_PointerType>(i);
|
||||
}
|
||||
}
|
||||
detail::dynamic_check(false, "Could not find free app pointer slot");
|
||||
|
|
@ -57,7 +57,8 @@ public:
|
|||
{
|
||||
RLBOX_ACQUIRE_UNIQUE_GUARD(lock, map_mutex);
|
||||
T_PointerType idx = get_unused_index();
|
||||
T_PointerTypeUnsigned idx_int = (T_PointerTypeUnsigned)idx;
|
||||
T_PointerTypeUnsigned idx_int =
|
||||
reinterpret_cast<T_PointerTypeUnsigned>(idx);
|
||||
pointer_map[idx_int] = ptr;
|
||||
return idx;
|
||||
}
|
||||
|
|
@ -65,7 +66,8 @@ public:
|
|||
void remove_app_ptr(T_PointerType idx)
|
||||
{
|
||||
RLBOX_ACQUIRE_UNIQUE_GUARD(lock, map_mutex);
|
||||
T_PointerTypeUnsigned idx_int = (T_PointerTypeUnsigned)idx;
|
||||
T_PointerTypeUnsigned idx_int =
|
||||
reinterpret_cast<T_PointerTypeUnsigned>(idx);
|
||||
auto it = pointer_map.find(idx_int);
|
||||
detail::dynamic_check(it != pointer_map.end(),
|
||||
"Error: removing a non-existing app pointer");
|
||||
|
|
@ -75,7 +77,8 @@ public:
|
|||
void* lookup_index(T_PointerType idx)
|
||||
{
|
||||
RLBOX_ACQUIRE_SHARED_GUARD(lock, map_mutex);
|
||||
T_PointerTypeUnsigned idx_int = (T_PointerTypeUnsigned)idx;
|
||||
T_PointerTypeUnsigned idx_int =
|
||||
reinterpret_cast<T_PointerTypeUnsigned>(idx);
|
||||
auto it = pointer_map.find(idx_int);
|
||||
detail::dynamic_check(it != pointer_map.end(),
|
||||
"Error: looking up a non-existing app pointer");
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ inline constexpr void convert_type_fundamental_or_array(T_To& to,
|
|||
is_signed_v<T_To_El> == is_signed_v<T_From_El>) {
|
||||
// Sanity check - this should definitely be true
|
||||
static_assert(sizeof(T_From_C) == sizeof(T_To_C));
|
||||
std::memcpy(&to, &from, sizeof(T_To_C));
|
||||
memcpy(&to, &from, sizeof(T_To_C));
|
||||
} else {
|
||||
for (size_t i = 0; i < std::extent_v<T_To_C>; i++) {
|
||||
convert_type_fundamental_or_array(to[i], from[i]);
|
||||
|
|
|
|||
309
third_party/rlbox/include/rlbox_dylib_sandbox.hpp
vendored
309
third_party/rlbox/include/rlbox_dylib_sandbox.hpp
vendored
|
|
@ -1,309 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <mutex>
|
||||
#ifndef RLBOX_USE_CUSTOM_SHARED_LOCK
|
||||
# include <shared_mutex>
|
||||
#endif
|
||||
#include <utility>
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Ensure the min/max macro in the header doesn't collide with functions in
|
||||
// std::
|
||||
# ifndef NOMINMAX
|
||||
# define NOMINMAX
|
||||
# endif
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include "rlbox_helpers.hpp"
|
||||
|
||||
namespace rlbox {
|
||||
|
||||
class rlbox_dylib_sandbox;
|
||||
|
||||
struct rlbox_dylib_sandbox_thread_data
|
||||
{
|
||||
rlbox_dylib_sandbox* sandbox;
|
||||
uint32_t last_callback_invoked;
|
||||
};
|
||||
|
||||
#ifdef RLBOX_EMBEDDER_PROVIDES_TLS_STATIC_VARIABLES
|
||||
|
||||
rlbox_dylib_sandbox_thread_data* get_rlbox_dylib_sandbox_thread_data();
|
||||
# define RLBOX_DYLIB_SANDBOX_STATIC_VARIABLES() \
|
||||
thread_local rlbox::rlbox_dylib_sandbox_thread_data \
|
||||
rlbox_dylib_sandbox_thread_info{ 0, 0 }; \
|
||||
namespace rlbox { \
|
||||
rlbox_dylib_sandbox_thread_data* get_rlbox_dylib_sandbox_thread_data() \
|
||||
{ \
|
||||
return &rlbox_dylib_sandbox_thread_info; \
|
||||
} \
|
||||
} \
|
||||
static_assert(true, "Enforce semi-colon")
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Class that implements the null sandbox. This sandbox doesn't actually
|
||||
* provide any isolation and only serves as a stepping stone towards migrating
|
||||
* an application to use the RLBox API.
|
||||
*/
|
||||
class rlbox_dylib_sandbox
|
||||
{
|
||||
public:
|
||||
// Stick with the system defaults
|
||||
using T_LongLongType = long long;
|
||||
using T_LongType = long;
|
||||
using T_IntType = int;
|
||||
using T_PointerType = void*;
|
||||
using T_ShortType = short;
|
||||
// no-op sandbox can transfer buffers as there is no sandboxings
|
||||
// Thus transfer is a noop
|
||||
using can_grant_deny_access = void;
|
||||
// if this plugin uses a separate function to lookup internal callbacks
|
||||
using needs_internal_lookup_symbol = void;
|
||||
|
||||
private:
|
||||
void* sandbox = nullptr;
|
||||
|
||||
RLBOX_SHARED_LOCK(callback_mutex);
|
||||
static inline const uint32_t MAX_CALLBACKS = 64;
|
||||
void* callback_unique_keys[MAX_CALLBACKS]{ 0 };
|
||||
void* callbacks[MAX_CALLBACKS]{ 0 };
|
||||
|
||||
#ifndef RLBOX_EMBEDDER_PROVIDES_TLS_STATIC_VARIABLES
|
||||
thread_local static inline rlbox_dylib_sandbox_thread_data thread_data{ 0,
|
||||
0 };
|
||||
#endif
|
||||
|
||||
template<uint32_t N, typename T_Ret, typename... T_Args>
|
||||
static T_Ret callback_trampoline(T_Args... params)
|
||||
{
|
||||
#ifdef RLBOX_EMBEDDER_PROVIDES_TLS_STATIC_VARIABLES
|
||||
auto& thread_data = *get_rlbox_dylib_sandbox_thread_data();
|
||||
#endif
|
||||
thread_data.last_callback_invoked = N;
|
||||
using T_Func = T_Ret (*)(T_Args...);
|
||||
T_Func func;
|
||||
{
|
||||
RLBOX_ACQUIRE_SHARED_GUARD(lock, thread_data.sandbox->callback_mutex);
|
||||
func = reinterpret_cast<T_Func>(thread_data.sandbox->callbacks[N]);
|
||||
}
|
||||
// Callbacks are invoked through function pointers, cannot use std::forward
|
||||
// as we don't have caller context for T_Args, which means they are all
|
||||
// effectively passed by value
|
||||
return func(params...);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
#if defined(_WIN32)
|
||||
using path_buf = const LPCWSTR;
|
||||
#else
|
||||
using path_buf = const char*;
|
||||
#endif
|
||||
|
||||
inline void impl_create_sandbox(path_buf path)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
sandbox = (void*)LoadLibraryW(path);
|
||||
#else
|
||||
sandbox = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
|
||||
#endif
|
||||
|
||||
if (!sandbox) {
|
||||
std::string error_msg = "Could not load dynamic library: ";
|
||||
#if defined(_WIN32)
|
||||
DWORD errorMessageID = GetLastError();
|
||||
if (errorMessageID != 0) {
|
||||
LPSTR messageBuffer = nullptr;
|
||||
// The api creates the buffer that holds the message
|
||||
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
errorMessageID,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPSTR)&messageBuffer,
|
||||
0,
|
||||
NULL);
|
||||
// Copy the error message into a std::string.
|
||||
std::string message(messageBuffer, size);
|
||||
error_msg += message;
|
||||
LocalFree(messageBuffer);
|
||||
}
|
||||
#else
|
||||
error_msg += dlerror();
|
||||
#endif
|
||||
detail::dynamic_check(false, error_msg.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
inline void impl_destroy_sandbox()
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
FreeLibrary((HMODULE)sandbox);
|
||||
#else
|
||||
dlclose(sandbox);
|
||||
#endif
|
||||
sandbox = nullptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void* impl_get_unsandboxed_pointer(T_PointerType p) const
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T_PointerType impl_get_sandboxed_pointer(const void* p) const
|
||||
{
|
||||
return const_cast<T_PointerType>(p);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline void* impl_get_unsandboxed_pointer_no_ctx(
|
||||
T_PointerType p,
|
||||
const void* /* example_unsandboxed_ptr */,
|
||||
rlbox_dylib_sandbox* (* // Func ptr
|
||||
/* param: expensive_sandbox_finder */)(
|
||||
const void* example_unsandboxed_ptr))
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline T_PointerType impl_get_sandboxed_pointer_no_ctx(
|
||||
const void* p,
|
||||
const void* /* example_unsandboxed_ptr */,
|
||||
rlbox_dylib_sandbox* (* // Func ptr
|
||||
/* param: expensive_sandbox_finder */)(
|
||||
const void* example_unsandboxed_ptr))
|
||||
{
|
||||
return const_cast<T_PointerType>(p);
|
||||
}
|
||||
|
||||
inline T_PointerType impl_malloc_in_sandbox(size_t size)
|
||||
{
|
||||
void* p = malloc(size);
|
||||
return p;
|
||||
}
|
||||
|
||||
inline void impl_free_in_sandbox(T_PointerType p) { free(p); }
|
||||
|
||||
static inline bool impl_is_in_same_sandbox(const void*, const void*)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool impl_is_pointer_in_sandbox_memory(const void*) { return true; }
|
||||
inline bool impl_is_pointer_in_app_memory(const void*) { return true; }
|
||||
|
||||
inline size_t impl_get_total_memory()
|
||||
{
|
||||
return std::numeric_limits<size_t>::max();
|
||||
}
|
||||
|
||||
inline void* impl_get_memory_location()
|
||||
{
|
||||
// There isn't any sandbox memory for the dylib_sandbox as we just redirect
|
||||
// to the app. Also, this is mostly used for pointer swizzling or sandbox
|
||||
// bounds checks which is also not present/not required. So we can just
|
||||
// return null
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* impl_lookup_symbol(const char* func_name)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
void* ret = GetProcAddress((HMODULE)sandbox, func_name);
|
||||
#else
|
||||
void* ret = dlsym(sandbox, func_name);
|
||||
#endif
|
||||
detail::dynamic_check(ret != nullptr, "Symbol not found");
|
||||
return ret;
|
||||
}
|
||||
|
||||
void* impl_internal_lookup_symbol(const char* func_name)
|
||||
{
|
||||
return impl_lookup_symbol(func_name);
|
||||
}
|
||||
|
||||
template<typename T, typename T_Converted, typename... T_Args>
|
||||
auto impl_invoke_with_func_ptr(T_Converted* func_ptr, T_Args&&... params)
|
||||
{
|
||||
#ifdef RLBOX_EMBEDDER_PROVIDES_TLS_STATIC_VARIABLES
|
||||
auto& thread_data = *get_rlbox_dylib_sandbox_thread_data();
|
||||
#endif
|
||||
thread_data.sandbox = this;
|
||||
return (*func_ptr)(params...);
|
||||
}
|
||||
|
||||
template<typename T_Ret, typename... T_Args>
|
||||
inline T_PointerType impl_register_callback(void* key, void* callback)
|
||||
{
|
||||
RLBOX_ACQUIRE_UNIQUE_GUARD(lock, callback_mutex);
|
||||
|
||||
void* chosen_trampoline = nullptr;
|
||||
|
||||
// need a compile time for loop as we we need I to be a compile time value
|
||||
// this is because we are returning the I'th callback trampoline
|
||||
detail::compile_time_for<MAX_CALLBACKS>([&](auto I) {
|
||||
if (!chosen_trampoline && callback_unique_keys[I.value] == nullptr) {
|
||||
callback_unique_keys[I.value] = key;
|
||||
callbacks[I.value] = callback;
|
||||
chosen_trampoline = reinterpret_cast<void*>(
|
||||
callback_trampoline<I.value, T_Ret, T_Args...>);
|
||||
}
|
||||
});
|
||||
|
||||
return reinterpret_cast<T_PointerType>(chosen_trampoline);
|
||||
}
|
||||
|
||||
static inline std::pair<rlbox_dylib_sandbox*, void*>
|
||||
impl_get_executed_callback_sandbox_and_key()
|
||||
{
|
||||
#ifdef RLBOX_EMBEDDER_PROVIDES_TLS_STATIC_VARIABLES
|
||||
auto& thread_data = *get_rlbox_dylib_sandbox_thread_data();
|
||||
#endif
|
||||
auto sandbox = thread_data.sandbox;
|
||||
auto callback_num = thread_data.last_callback_invoked;
|
||||
void* key = sandbox->callback_unique_keys[callback_num];
|
||||
return std::make_pair(sandbox, key);
|
||||
}
|
||||
|
||||
template<typename T_Ret, typename... T_Args>
|
||||
inline void impl_unregister_callback(void* key)
|
||||
{
|
||||
RLBOX_ACQUIRE_UNIQUE_GUARD(lock, callback_mutex);
|
||||
for (uint32_t i = 0; i < MAX_CALLBACKS; i++) {
|
||||
if (callback_unique_keys[i] == key) {
|
||||
callback_unique_keys[i] = nullptr;
|
||||
callbacks[i] = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T* impl_grant_access(T* src, size_t num, bool& success)
|
||||
{
|
||||
RLBOX_UNUSED(num);
|
||||
success = true;
|
||||
return src;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T* impl_deny_access(T* src, size_t num, bool& success)
|
||||
{
|
||||
RLBOX_UNUSED(num);
|
||||
success = true;
|
||||
return src;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
11
third_party/rlbox/include/rlbox_helpers.hpp
vendored
11
third_party/rlbox/include/rlbox_helpers.hpp
vendored
|
|
@ -7,9 +7,6 @@
|
|||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#ifndef RLBOX_USE_CUSTOM_SHARED_LOCK
|
||||
#include <mutex>
|
||||
#endif
|
||||
|
||||
#include "rlbox_stdlib_polyfill.hpp"
|
||||
|
||||
|
|
@ -24,12 +21,8 @@ namespace detail {
|
|||
#if __cpp_exceptions && defined(RLBOX_USE_EXCEPTIONS)
|
||||
throw std::runtime_error(msg);
|
||||
#else
|
||||
#ifdef RLBOX_CUSTOM_ABORT
|
||||
RLBOX_CUSTOM_ABORT(msg);
|
||||
#else
|
||||
std::cerr << msg << std::endl;
|
||||
std::abort();
|
||||
#endif
|
||||
std::cerr << msg << std::endl;
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
// clang-format on
|
||||
|
|
|
|||
14
third_party/rlbox/include/rlbox_noop_sandbox.hpp
vendored
14
third_party/rlbox/include/rlbox_noop_sandbox.hpp
vendored
|
|
@ -104,9 +104,10 @@ protected:
|
|||
static inline void* impl_get_unsandboxed_pointer_no_ctx(
|
||||
T_PointerType p,
|
||||
const void* /* example_unsandboxed_ptr */,
|
||||
rlbox_noop_sandbox* (* // Func ptr
|
||||
/* param: expensive_sandbox_finder */)(
|
||||
const void* example_unsandboxed_ptr))
|
||||
rlbox_noop_sandbox* (
|
||||
* // Func ptr
|
||||
/* param: expensive_sandbox_finder */)(const void*
|
||||
example_unsandboxed_ptr))
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
|
@ -115,9 +116,10 @@ protected:
|
|||
static inline T_PointerType impl_get_sandboxed_pointer_no_ctx(
|
||||
const void* p,
|
||||
const void* /* example_unsandboxed_ptr */,
|
||||
rlbox_noop_sandbox* (* // Func ptr
|
||||
/* param: expensive_sandbox_finder */)(
|
||||
const void* example_unsandboxed_ptr))
|
||||
rlbox_noop_sandbox* (
|
||||
* // Func ptr
|
||||
/* param: expensive_sandbox_finder */)(const void*
|
||||
example_unsandboxed_ptr))
|
||||
{
|
||||
return const_cast<T_PointerType>(p);
|
||||
}
|
||||
|
|
|
|||
73
third_party/rlbox/include/rlbox_sandbox.hpp
vendored
73
third_party/rlbox/include/rlbox_sandbox.hpp
vendored
|
|
@ -327,14 +327,13 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
detail::dynamic_check(
|
||||
false,
|
||||
"Internal error: Could not find the sandbox associated with example "
|
||||
"pointer. Please file a bug.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<typename... T_Args>
|
||||
static auto impl_create_sandbox_helper(rlbox_sandbox<T_Sbx>* this_ptr, T_Args... args) {
|
||||
return this_ptr->impl_create_sandbox(std::forward<T_Args>(args)...);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Unused member that allows the calling code to save data in a
|
||||
|
|
@ -363,7 +362,7 @@ public:
|
|||
* implementation. For the null sandbox, no arguments are necessary.
|
||||
*/
|
||||
template<typename... T_Args>
|
||||
inline bool create_sandbox(T_Args... args)
|
||||
inline auto create_sandbox(T_Args... args)
|
||||
{
|
||||
#ifdef RLBOX_MEASURE_TRANSITION_TIMES
|
||||
// Warm up the timer. The first call is always slow (at least on the test
|
||||
|
|
@ -381,27 +380,15 @@ public:
|
|||
"create_sandbox called when sandbox already created/is being "
|
||||
"created concurrently");
|
||||
|
||||
using T_Result = rlbox::detail::polyfill::invoke_result_t<decltype(impl_create_sandbox_helper<T_Args...>), decltype(this), T_Args...>;
|
||||
|
||||
bool created = true;
|
||||
if constexpr (std::is_same_v<T_Result, void>) {
|
||||
this->impl_create_sandbox(std::forward<T_Args>(args)...);
|
||||
} else if constexpr (std::is_same_v<T_Result, bool>) {
|
||||
created = this->impl_create_sandbox(std::forward<T_Args>(args)...);
|
||||
} else {
|
||||
rlbox_detail_static_fail_because(
|
||||
(!std::is_same_v<T_Result, void> && !std::is_same_v<T_Result, bool>),
|
||||
"Expected impl_create_sandbox to return void or a boolean"
|
||||
);
|
||||
}
|
||||
|
||||
if (created) {
|
||||
sandbox_created.store(Sandbox_Status::CREATED);
|
||||
RLBOX_ACQUIRE_UNIQUE_GUARD(lock, sandbox_list_lock);
|
||||
sandbox_list.push_back(this);
|
||||
}
|
||||
|
||||
return created;
|
||||
return detail::return_first_result(
|
||||
[&]() {
|
||||
return this->impl_create_sandbox(std::forward<T_Args>(args)...);
|
||||
},
|
||||
[&]() {
|
||||
sandbox_created.store(Sandbox_Status::CREATED);
|
||||
RLBOX_ACQUIRE_UNIQUE_GUARD(lock, sandbox_list_lock);
|
||||
sandbox_list.push_back(this);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -600,13 +587,7 @@ public:
|
|||
*/
|
||||
static inline bool is_in_same_sandbox(const void* p1, const void* p2)
|
||||
{
|
||||
const size_t num_args =
|
||||
detail::func_arg_nums_v<decltype(T_Sbx::impl_is_in_same_sandbox)>;
|
||||
if constexpr (num_args == 2) {
|
||||
return T_Sbx::impl_is_in_same_sandbox(p1, p2);
|
||||
} else {
|
||||
return T_Sbx::impl_is_in_same_sandbox(p1, p2, find_sandbox_from_example);
|
||||
}
|
||||
return T_Sbx::impl_is_in_same_sandbox(p1, p2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -692,28 +673,6 @@ public:
|
|||
return func_ptr;
|
||||
}
|
||||
|
||||
void* internal_lookup_symbol(const char* func_name)
|
||||
{
|
||||
{
|
||||
RLBOX_ACQUIRE_SHARED_GUARD(lock, func_ptr_cache_lock);
|
||||
|
||||
auto func_ptr_ref = func_ptr_map.find(func_name);
|
||||
if (func_ptr_ref != func_ptr_map.end()) {
|
||||
return func_ptr_ref->second;
|
||||
}
|
||||
}
|
||||
|
||||
void* func_ptr = 0;
|
||||
if constexpr(rlbox::detail::has_member_using_needs_internal_lookup_symbol_v<T_Sbx>) {
|
||||
func_ptr = this->impl_internal_lookup_symbol(func_name);
|
||||
} else {
|
||||
func_ptr = this->impl_lookup_symbol(func_name);
|
||||
}
|
||||
RLBOX_ACQUIRE_UNIQUE_GUARD(lock, func_ptr_cache_lock);
|
||||
func_ptr_map[func_name] = func_ptr;
|
||||
return func_ptr;
|
||||
}
|
||||
|
||||
// this is an internal function invoked from macros, so it has be public
|
||||
template<typename T, typename... T_Args>
|
||||
inline auto INTERNAL_invoke_with_func_name(const char* func_name,
|
||||
|
|
@ -946,7 +905,7 @@ public:
|
|||
inline tainted<T*, T_Sbx> INTERNAL_get_sandbox_function_name(
|
||||
const char* func_name)
|
||||
{
|
||||
return INTERNAL_get_sandbox_function_ptr<T>(internal_lookup_symbol(func_name));
|
||||
return INTERNAL_get_sandbox_function_ptr<T>(lookup_symbol(func_name));
|
||||
}
|
||||
|
||||
// this is an internal function invoked from macros, so it has be public
|
||||
|
|
|
|||
20
third_party/rlbox/include/rlbox_stdlib.hpp
vendored
20
third_party/rlbox/include/rlbox_stdlib.hpp
vendored
|
|
@ -130,12 +130,7 @@ inline T_Wrap<T_Rhs*, T_Sbx> memset(rlbox_sandbox<T_Sbx>& sandbox,
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Copy to sandbox memory area. Note that memcpy is meant to be called on
|
||||
* byte arrays does not adjust data according to ABI differences. If the
|
||||
* programmer does accidentally call memcpy on buffers that needs ABI
|
||||
* adjustment, this may cause compatibility issues, but will not cause a
|
||||
* security issue as the destination is always a tainted or tainted_volatile
|
||||
* pointer
|
||||
* @brief Copy to sandbox memory area.
|
||||
*/
|
||||
template<typename T_Sbx,
|
||||
typename T_Rhs,
|
||||
|
|
@ -225,18 +220,13 @@ tainted<T*, T_Sbx> copy_memory_or_grant_access(rlbox_sandbox<T_Sbx>& sandbox,
|
|||
bool free_source_on_copy,
|
||||
bool& copied)
|
||||
{
|
||||
// Malloc in sandbox takes a uint32_t as the parameter, need a bounds check
|
||||
detail::dynamic_check(num <= std::numeric_limits<uint32_t>::max(),
|
||||
"Granting access too large a region");
|
||||
uint32_t num_trunc = num;
|
||||
|
||||
// sandbox can grant access if it includes the following line
|
||||
// using can_grant_deny_access = void;
|
||||
if constexpr (detail::has_member_using_can_grant_deny_access_v<T_Sbx>) {
|
||||
detail::check_range_doesnt_cross_app_sbx_boundary<T_Sbx>(src, num_trunc);
|
||||
detail::check_range_doesnt_cross_app_sbx_boundary<T_Sbx>(src, num);
|
||||
|
||||
bool success;
|
||||
auto ret = sandbox.INTERNAL_grant_access(src, num_trunc, success);
|
||||
auto ret = sandbox.INTERNAL_grant_access(src, num, success);
|
||||
if (success) {
|
||||
copied = false;
|
||||
return ret;
|
||||
|
|
@ -245,8 +235,8 @@ tainted<T*, T_Sbx> copy_memory_or_grant_access(rlbox_sandbox<T_Sbx>& sandbox,
|
|||
|
||||
using T_nocv = std::remove_cv_t<T>;
|
||||
tainted<T_nocv*, T_Sbx> copy =
|
||||
sandbox.template malloc_in_sandbox<T_nocv>(num_trunc);
|
||||
rlbox::memcpy(sandbox, copy, src, num_trunc);
|
||||
sandbox.template malloc_in_sandbox<T_nocv>(num);
|
||||
rlbox::memcpy(sandbox, copy, src, num);
|
||||
if (free_source_on_copy) {
|
||||
free(const_cast<void*>(reinterpret_cast<const void*>(src)));
|
||||
}
|
||||
|
|
|
|||
34
third_party/rlbox/include/rlbox_type_traits.hpp
vendored
34
third_party/rlbox/include/rlbox_type_traits.hpp
vendored
|
|
@ -27,40 +27,6 @@ using valid_return_t =
|
|||
template<typename T>
|
||||
using valid_param_t = std::conditional_t<std::is_void_v<T>, void*, T>;
|
||||
|
||||
namespace func_first_arg_detail {
|
||||
template<typename Ret, typename Arg, typename... Rest>
|
||||
Arg func_first_arg_t_helper(Ret(*) (Arg, Rest...));
|
||||
|
||||
template<typename Ret, typename F, typename Arg, typename... Rest>
|
||||
Arg func_first_arg_t_helper(Ret(F::*) (Arg, Rest...));
|
||||
|
||||
template<typename Ret, typename F, typename Arg, typename... Rest>
|
||||
Arg func_first_arg_t_helper(Ret(F::*) (Arg, Rest...) const);
|
||||
|
||||
template <typename F>
|
||||
decltype(func_first_arg_t_helper(&F::operator())) first_argument_helper(F);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
using func_first_arg_t = decltype(func_first_arg_detail::first_argument_helper(std::declval<T>()));
|
||||
|
||||
namespace func_arg_nums_v_detail {
|
||||
template<typename T_Ret, typename... T_Args>
|
||||
constexpr size_t helper_two(T_Ret (*)(T_Args...))
|
||||
{
|
||||
return sizeof...(T_Args);
|
||||
}
|
||||
template<typename T_Func>
|
||||
constexpr size_t helper()
|
||||
{
|
||||
constexpr T_Func* ptr = nullptr;
|
||||
return helper_two(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T_Func>
|
||||
constexpr size_t func_arg_nums_v = func_arg_nums_v_detail::helper<T_Func>();
|
||||
|
||||
template<typename T>
|
||||
using valid_array_el_t =
|
||||
std::conditional_t<std::is_void_v<T> || std::is_function_v<T>, int, T>;
|
||||
|
|
|
|||
2
third_party/rlbox/include/rlbox_types.hpp
vendored
2
third_party/rlbox/include/rlbox_types.hpp
vendored
|
|
@ -102,6 +102,4 @@ template<typename T, typename T_Sbx>
|
|||
class app_pointer;
|
||||
|
||||
class rlbox_noop_sandbox;
|
||||
|
||||
class rlbox_dylib_sandbox;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,21 +151,4 @@ constexpr bool has_member_using_can_grant_deny_access_v =
|
|||
detail_has_member_using_can_grant_deny_access::
|
||||
has_member_using_can_grant_deny_access<T>::value;
|
||||
|
||||
namespace detail_has_member_using_needs_internal_lookup_symbol {
|
||||
template<class T, class Enable = void>
|
||||
struct has_member_using_needs_internal_lookup_symbol : std::false_type
|
||||
{};
|
||||
|
||||
template<class T>
|
||||
struct has_member_using_needs_internal_lookup_symbol<
|
||||
T,
|
||||
std::void_t<typename T::needs_internal_lookup_symbol>> : std::true_type
|
||||
{};
|
||||
}
|
||||
|
||||
template<class T>
|
||||
constexpr bool has_member_using_needs_internal_lookup_symbol_v =
|
||||
detail_has_member_using_needs_internal_lookup_symbol::
|
||||
has_member_using_needs_internal_lookup_symbol<T>::value;
|
||||
|
||||
}
|
||||
|
|
@ -2116,6 +2116,7 @@ def wasm_sandboxing_libraries():
|
|||
def default_wasm_sandboxing_libraries(libraries, target, automation):
|
||||
non_default_libs = set()
|
||||
if target.bitness == 32:
|
||||
non_default_libs.add("hunspell")
|
||||
non_default_libs.add("ogg")
|
||||
|
||||
if automation:
|
||||
|
|
|
|||
Loading…
Reference in a new issue