Avoid sanitizer macros use Abseil's where necessary

Using C++17 means we can get rid of many `#ifdef`s by using `if constexpr`.
This way, we ensure that both branches compile and still retain zero runtime
overhead.

Note that open source builds of Sandboxed API do not ship with sanitizer
configurations yet. This will be added in follow-up changes.

PiperOrigin-RevId: 354932160
Change-Id: I3678dffc47ea873919f0a8c01f3a7d999fc29a5b
This commit is contained in:
Christian Blichmann 2021-02-01 07:10:43 -08:00 committed by Copybara-Service
parent 6dcef3d5c9
commit 55a8373ec3
25 changed files with 200 additions and 189 deletions

View File

@ -73,18 +73,17 @@ cc_library(
copts = sapi_platform_copts(), copts = sapi_platform_copts(),
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
":config",
":embed_file", ":embed_file",
":vars", ":vars",
"//sandboxed_api/sandbox2", "//sandboxed_api/sandbox2",
"//sandboxed_api/sandbox2:client", "//sandboxed_api/sandbox2:client",
"//sandboxed_api/sandbox2:comms", "//sandboxed_api/sandbox2:comms",
"//sandboxed_api/sandbox2:util",
"//sandboxed_api/sandbox2/util:bpf_helper", "//sandboxed_api/sandbox2/util:bpf_helper",
"//sandboxed_api/util:file_base", "//sandboxed_api/util:file_base",
"//sandboxed_api/util:fileops", "//sandboxed_api/util:fileops",
"//sandboxed_api/util:runfiles", "//sandboxed_api/util:runfiles",
"//sandboxed_api/util:status", "//sandboxed_api/util:status",
"//sandboxed_api/util:strerror",
"@com_google_absl//absl/base", "@com_google_absl//absl/base",
"@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/container:flat_hash_map",
@ -176,6 +175,7 @@ cc_library(
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
":call", ":call",
":config",
":lenval_core", ":lenval_core",
":proto_arg_cc_proto", ":proto_arg_cc_proto",
":vars", ":vars",
@ -184,6 +184,7 @@ cc_library(
"//sandboxed_api/sandbox2:forkingclient", "//sandboxed_api/sandbox2:forkingclient",
"//sandboxed_api/sandbox2:logsink", "//sandboxed_api/sandbox2:logsink",
"//sandboxed_api/util:flags", "//sandboxed_api/util:flags",
"@com_google_absl//absl/base:dynamic_annotations",
"@com_google_absl//absl/strings", "@com_google_absl//absl/strings",
"@com_google_glog//:glog", "@com_google_glog//:glog",
"@com_google_protobuf//:protobuf", "@com_google_protobuf//:protobuf",
@ -198,6 +199,7 @@ cc_test(
tags = ["local"], tags = ["local"],
deps = [ deps = [
":sapi", ":sapi",
":testing",
"//sandboxed_api/examples/stringop/lib:stringop-sapi", "//sandboxed_api/examples/stringop/lib:stringop-sapi",
"//sandboxed_api/examples/stringop/lib:stringop_params_cc_proto", "//sandboxed_api/examples/stringop/lib:stringop_params_cc_proto",
"//sandboxed_api/examples/sum/lib:sum-sapi", "//sandboxed_api/examples/sum/lib:sum-sapi",

View File

@ -172,6 +172,7 @@ add_library(sapi_client ${SAPI_LIB_TYPE}
add_library(sapi::client ALIAS sapi_client) add_library(sapi::client ALIAS sapi_client)
target_link_libraries(sapi_client target_link_libraries(sapi_client
PRIVATE absl::core_headers PRIVATE absl::core_headers
absl::dynamic_annotations
absl::strings absl::strings
libffi::libffi libffi::libffi
sandbox2::client sandbox2::client
@ -189,6 +190,18 @@ target_link_libraries(sapi_client
) )
if(SAPI_ENABLE_TESTS AND NOT CMAKE_CROSSCOMPILING) if(SAPI_ENABLE_TESTS AND NOT CMAKE_CROSSCOMPILING)
# sandboxed_api:testing
add_library(sapi_testing ${SAPI_LIB_TYPE}
testing.cc
testing.h
)
add_library(sapi::testing ALIAS sapi_testing)
target_link_libraries(sapi_testing PRIVATE
absl::strings
sapi::file_base
sapi::base
)
# sandboxed_api:sapi_test # sandboxed_api:sapi_test
add_executable(sapi_test add_executable(sapi_test
sapi_test.cc sapi_test.cc
@ -206,21 +219,9 @@ if(SAPI_ENABLE_TESTS AND NOT CMAKE_CROSSCOMPILING)
sapi::stringop_sapi sapi::stringop_sapi
sapi::sum_sapi sapi::sum_sapi
sapi::test_main sapi::test_main
sapi::testing
) )
gtest_discover_tests_xcompile(sapi_test) gtest_discover_tests_xcompile(sapi_test)
# sandboxed_api:testing
add_library(sapi_testing ${SAPI_LIB_TYPE}
testing.cc
testing.h
)
add_library(sapi::testing ALIAS sapi_testing)
target_link_libraries(sapi_testing PRIVATE
absl::strings
sapi::file_base
sapi::base
)
endif() endif()
# Install headers and libraries, excluding tools, tests and examples # Install headers and libraries, excluding tools, tests and examples

View File

@ -78,14 +78,14 @@ struct FuncCall {
struct FuncRet { struct FuncRet {
// Return type: // Return type:
v::Type ret_type; v::Type ret_type = v::Type::kVoid;
// Return value. // Return value.
union { union {
uintptr_t int_val; uintptr_t int_val = 0;
long double float_val; long double float_val;
}; };
// Status of the operation: success/failure. // Status of the operation: success/failure.
bool success; bool success = false;
}; };
} // namespace sapi } // namespace sapi

View File

@ -25,9 +25,11 @@
#include <glog/logging.h> #include <glog/logging.h>
#include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.h"
#include "google/protobuf/message.h" #include "google/protobuf/message.h"
#include "absl/base/dynamic_annotations.h"
#include "sandboxed_api/util/flag.h" #include "sandboxed_api/util/flag.h"
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#include "sandboxed_api/call.h" #include "sandboxed_api/call.h"
#include "sandboxed_api/config.h"
#include "sandboxed_api/lenval_core.h" #include "sandboxed_api/lenval_core.h"
#include "sandboxed_api/proto_arg.pb.h" #include "sandboxed_api/proto_arg.pb.h"
#include "sandboxed_api/sandbox2/comms.h" #include "sandboxed_api/sandbox2/comms.h"
@ -35,10 +37,6 @@
#include "sandboxed_api/sandbox2/logsink.h" #include "sandboxed_api/sandbox2/logsink.h"
#include "sandboxed_api/vars.h" #include "sandboxed_api/vars.h"
#ifdef MEMORY_SANITIZER
#include <sanitizer/allocator_interface.h>
#endif
#include <ffi.h> #include <ffi.h>
#include <ffitarget.h> #include <ffitarget.h>
@ -232,15 +230,14 @@ void HandleCallMsg(const FuncCall& call, FuncRet* ret) {
void HandleAllocMsg(const size_t size, FuncRet* ret) { void HandleAllocMsg(const size_t size, FuncRet* ret) {
VLOG(1) << "HandleAllocMsg: size=" << size; VLOG(1) << "HandleAllocMsg: size=" << size;
ret->ret_type = v::Type::kPointer; const void* allocated = malloc(size);
#ifdef MEMORY_SANITIZER
// Memory is copied to the pointer using an API that the memory sanitizer // Memory is copied to the pointer using an API that the memory sanitizer
// is blind to (process_vm_writev). Initialize the memory here so that // is blind to (process_vm_writev). Mark the memory as initialized here, so
// the sandboxed code can still be tested with the memory sanitizer. // that the sandboxed code can still be tested using MSAN.
ret->int_val = reinterpret_cast<uintptr_t>(calloc(1, size)); ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(allocated, size);
#else
ret->int_val = reinterpret_cast<uintptr_t>(malloc(size)); ret->ret_type = v::Type::kPointer;
#endif ret->int_val = reinterpret_cast<uintptr_t>(allocated);
ret->success = true; ret->success = true;
} }
@ -248,23 +245,16 @@ void HandleAllocMsg(const size_t size, FuncRet* ret) {
void HandleReallocMsg(uintptr_t ptr, size_t size, FuncRet* ret) { void HandleReallocMsg(uintptr_t ptr, size_t size, FuncRet* ret) {
VLOG(1) << "HandleReallocMsg(" << absl::StrCat(absl::Hex(ptr)) << ", " << size VLOG(1) << "HandleReallocMsg(" << absl::StrCat(absl::Hex(ptr)) << ", " << size
<< ")"; << ")";
#ifdef MEMORY_SANITIZER
const size_t orig_size = const void* reallocated = realloc(reinterpret_cast<void*>(ptr), size);
__sanitizer_get_allocated_size(reinterpret_cast<const void*>(ptr));
#endif
ret->ret_type = v::Type::kPointer;
ret->int_val =
reinterpret_cast<uintptr_t>(realloc(reinterpret_cast<void*>(ptr), size));
ret->success = true;
#ifdef MEMORY_SANITIZER
// Memory is copied to the pointer using an API that the memory sanitizer // Memory is copied to the pointer using an API that the memory sanitizer
// is blind to (process_vm_writev). Initialize the memory here so that // is blind to (process_vm_writev). Mark the memory as initialized here, so
// the sandboxed code can still be tested with the memory sanitizer. // that the sandboxed code can still be tested using MSAN.
if (orig_size < size && ret->int_val != 0) { ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(reallocated, size);
memset(reinterpret_cast<void*>(ret->int_val + orig_size), 0,
size - orig_size); ret->ret_type = v::Type::kPointer;
} ret->int_val = reinterpret_cast<uintptr_t>(reallocated);
#endif ret->success = true;
} }
// Handles requests to free memory previously allocated by HandleAllocMsg() and // Handles requests to free memory previously allocated by HandleAllocMsg() and
@ -350,10 +340,11 @@ void ServeRequest(sandbox2::Comms* comms) {
CHECK(comms->RecvTLV(&tag, &bytes)); CHECK(comms->RecvTLV(&tag, &bytes));
FuncRet ret{}; FuncRet ret = {
ret.ret_type = v::Type::kVoid; .ret_type = v::Type::kVoid,
ret.int_val = static_cast<uintptr_t>(Error::kUnset); .int_val = static_cast<uintptr_t>(Error::kUnset),
ret.success = false; .success = false,
};
switch (tag) { switch (tag) {
case comms::kMsgCall: case comms::kMsgCall:

View File

@ -92,6 +92,37 @@ static_assert(host_cpu::Architecture() != cpu::kUnknown,
"Host CPU architecture is not supported: One of x86-64, POWER64 " "Host CPU architecture is not supported: One of x86-64, POWER64 "
"(little endian), Arm or AArch64 is required."); "(little endian), Arm or AArch64 is required.");
namespace sanitizers {
constexpr bool IsMSan() {
#ifdef ABSL_HAVE_MEMORY_SANITIZER
return true;
#else
return false;
#endif
}
constexpr bool IsTSan() {
#ifdef ABSL_HAVE_THREAD_SANITIZER
return true;
#else
return false;
#endif
}
constexpr bool IsASan() {
#ifdef ABSL_HAVE_ADDRESS_SANITIZER
return true;
#else
return false;
#endif
}
// Returns whether any of the sanitizers is enabled.
constexpr bool IsAny() { return IsMSan() || IsTSan() || IsASan(); }
} // namespace sanitizers
} // namespace sapi } // namespace sapi
#endif // SANDBOXED_API_CONFIG_H_ #endif // SANDBOXED_API_CONFIG_H_

View File

@ -31,14 +31,14 @@
#include "sandboxed_api/util/status_matchers.h" #include "sandboxed_api/util/status_matchers.h"
#include "sandboxed_api/vars.h" #include "sandboxed_api/vars.h"
namespace {
using ::sapi::IsOk; using ::sapi::IsOk;
using ::testing::Eq; using ::testing::Eq;
using ::testing::Ne; using ::testing::Ne;
using ::testing::SizeIs; using ::testing::SizeIs;
using ::testing::StrEq; using ::testing::StrEq;
namespace {
// Tests using a simple transaction (and function pointers): // Tests using a simple transaction (and function pointers):
TEST(StringopTest, ProtobufStringDuplication) { TEST(StringopTest, ProtobufStringDuplication) {
sapi::BasicTransaction st(absl::make_unique<StringopSapiSandbox>()); sapi::BasicTransaction st(absl::make_unique<StringopSapiSandbox>());

View File

@ -31,6 +31,7 @@
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h" #include "absl/strings/str_format.h"
#include "absl/time/time.h" #include "absl/time/time.h"
#include "sandboxed_api/config.h"
#include "sandboxed_api/embed_file.h" #include "sandboxed_api/embed_file.h"
#include "sandboxed_api/rpcchannel.h" #include "sandboxed_api/rpcchannel.h"
#include "sandboxed_api/sandbox2/executor.h" #include "sandboxed_api/sandbox2/executor.h"
@ -92,12 +93,11 @@ void InitDefaultPolicyBuilder(sandbox2::PolicyBuilder* builder) {
}) })
.AddFile("/etc/localtime") .AddFile("/etc/localtime")
.AddTmpfs("/tmp", 1ULL << 30 /* 1GiB tmpfs (max size) */); .AddTmpfs("/tmp", 1ULL << 30 /* 1GiB tmpfs (max size) */);
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \ if constexpr (sanitizers::IsAny()) {
defined(THREAD_SANITIZER) LOG(WARNING) << "Allowing additional calls to support the LLVM "
LOG(WARNING) << "Allowing additional calls to support the LLVM " << "(ASAN/MSAN/TSAN) sanitizer";
<< "(ASAN/MSAN/TSAN) sanitizer"; builder->AllowLlvmSanitizers();
builder->AllowLlvmSanitizers(); }
#endif
} }
void Sandbox::Terminate(bool attempt_graceful_exit) { void Sandbox::Terminate(bool attempt_graceful_exit) {

View File

@ -604,7 +604,9 @@ cc_library(
"//sandboxed_api/util:status", "//sandboxed_api/util:status",
"//sandboxed_api/util:status_cc_proto", "//sandboxed_api/util:status_cc_proto",
"//sandboxed_api/util:strerror", "//sandboxed_api/util:strerror",
"@com_google_absl//absl/base:config",
"@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/base:dynamic_annotations",
"@com_google_absl//absl/memory", "@com_google_absl//absl/memory",
"@com_google_absl//absl/status", "@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor", "@com_google_absl//absl/status:statusor",
@ -829,6 +831,7 @@ cc_test(
deps = [ deps = [
":comms", ":comms",
":sandbox2", ":sandbox2",
"//sandboxed_api:config",
"//sandboxed_api:testing", "//sandboxed_api:testing",
"//sandboxed_api/sandbox2/util:bpf_helper", "//sandboxed_api/sandbox2/util:bpf_helper",
"//sandboxed_api/util:status_matchers", "//sandboxed_api/util:status_matchers",

View File

@ -34,6 +34,8 @@
#include <functional> #include <functional>
#include "google/protobuf/message.h" #include "google/protobuf/message.h"
#include "absl/base/config.h"
#include "absl/base/dynamic_annotations.h"
#include "absl/memory/memory.h" #include "absl/memory/memory.h"
#include "absl/status/status.h" #include "absl/status/status.h"
#include "absl/status/statusor.h" #include "absl/status/statusor.h"
@ -45,10 +47,6 @@
#include "sandboxed_api/util/status.h" #include "sandboxed_api/util/status.h"
#include "sandboxed_api/util/strerror.h" #include "sandboxed_api/util/strerror.h"
#ifdef MEMORY_SANITIZER
#include "base/dynamic_annotations.h"
#endif
namespace sandbox2 { namespace sandbox2 {
// Future extension point used to mark code sections that invoke syscalls that // Future extension point used to mark code sections that invoke syscalls that
@ -241,13 +239,11 @@ bool Comms::SendTLV(uint32_t tag, size_t length, const void* value) {
if (!Send(&length, sizeof(length))) { if (!Send(&length, sizeof(length))) {
return false; return false;
} }
if (length > 0) { if (length > 0 && !Send(value, length)) {
if (!Send(value, length)) { return false;
return false;
}
} }
return true;
} }
return true;
} }
bool Comms::RecvString(std::string* v) { bool Comms::RecvString(std::string* v) {
@ -358,9 +354,7 @@ bool Comms::RecvFD(int* fd) {
// msg struct has been fully populated. Apparently MSAN is not aware of // msg struct has been fully populated. Apparently MSAN is not aware of
// syscall(__NR_recvmsg) semantics so we need to suppress the error (here and // syscall(__NR_recvmsg) semantics so we need to suppress the error (here and
// everywhere below). // everywhere below).
#ifdef MEMORY_SANITIZER
ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(&tlv, sizeof(tlv)); ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(&tlv, sizeof(tlv));
#endif
if (tlv.tag != kTagFd) { if (tlv.tag != kTagFd) {
SAPI_RAW_LOG(ERROR, "Expected (kTagFD: 0x%x), got: 0x%u", kTagFd, tlv.tag); SAPI_RAW_LOG(ERROR, "Expected (kTagFD: 0x%x), got: 0x%u", kTagFd, tlv.tag);
@ -368,9 +362,7 @@ bool Comms::RecvFD(int* fd) {
} }
cmsg = CMSG_FIRSTHDR(&msg); cmsg = CMSG_FIRSTHDR(&msg);
#ifdef MEMORY_SANITIZER
ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(cmsg, sizeof(cmsghdr)); ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(cmsg, sizeof(cmsghdr));
#endif
while (cmsg) { while (cmsg) {
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) { if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) {
@ -381,9 +373,7 @@ bool Comms::RecvFD(int* fd) {
} }
int* fds = reinterpret_cast<int*>(CMSG_DATA(cmsg)); int* fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
*fd = fds[0]; *fd = fds[0];
#ifdef MEMORY_SANITIZER
ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(fd, sizeof(int)); ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(fd, sizeof(int));
#endif
return true; return true;
} }
cmsg = CMSG_NXTHDR(&msg, cmsg); cmsg = CMSG_NXTHDR(&msg, cmsg);

View File

@ -30,6 +30,7 @@ cc_binary(
copts = sapi_platform_copts(), copts = sapi_platform_copts(),
data = [":crc4bin"], data = [":crc4bin"],
deps = [ deps = [
"//sandboxed_api:config",
"//sandboxed_api/sandbox2", "//sandboxed_api/sandbox2",
"//sandboxed_api/sandbox2:comms", "//sandboxed_api/sandbox2:comms",
"//sandboxed_api/sandbox2/util:bpf_helper", "//sandboxed_api/sandbox2/util:bpf_helper",

View File

@ -30,6 +30,7 @@
#include <glog/logging.h> #include <glog/logging.h>
#include "sandboxed_api/util/flag.h" #include "sandboxed_api/util/flag.h"
#include "absl/memory/memory.h" #include "absl/memory/memory.h"
#include "sandboxed_api/config.h"
#include "sandboxed_api/sandbox2/comms.h" #include "sandboxed_api/sandbox2/comms.h"
#include "sandboxed_api/sandbox2/executor.h" #include "sandboxed_api/sandbox2/executor.h"
#include "sandboxed_api/sandbox2/limits.h" #include "sandboxed_api/sandbox2/limits.h"
@ -40,7 +41,7 @@
#include "sandboxed_api/sandbox2/util/bpf_helper.h" #include "sandboxed_api/sandbox2/util/bpf_helper.h"
#include "sandboxed_api/util/runfiles.h" #include "sandboxed_api/util/runfiles.h"
using std::string; using std::string; // gflags <-> Abseil Flags
ABSL_FLAG(string, input, "", "Input to calculate CRC4 of."); ABSL_FLAG(string, input, "", "Input to calculate CRC4 of.");
ABSL_FLAG(bool, call_syscall_not_allowed, false, ABSL_FLAG(bool, call_syscall_not_allowed, false,
@ -49,21 +50,21 @@ ABSL_FLAG(bool, call_syscall_not_allowed, false,
namespace { namespace {
std::unique_ptr<sandbox2::Policy> GetPolicy() { std::unique_ptr<sandbox2::Policy> GetPolicy() {
return sandbox2::PolicyBuilder() sandbox2::PolicyBuilder builder;
.DisableNamespaces() builder.DisableNamespaces().AllowExit().AddPolicyOnSyscalls(
.AllowExit() {__NR_read, __NR_write, __NR_close},
.AddPolicyOnSyscalls( {
{__NR_read, __NR_write, __NR_close}, ARG_32(0),
{ARG_32(0), JEQ32(sandbox2::Comms::kSandbox2ClientCommsFD, ALLOW)}) JEQ32(sandbox2::Comms::kSandbox2ClientCommsFD, ALLOW),
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \ });
defined(THREAD_SANITIZER) if constexpr (sapi::sanitizers::IsAny()) {
.AllowSyscall(__NR_mmap) builder.AllowSyscall(__NR_mmap);
#endif }
.BuildOrDie(); return builder.BuildOrDie();
} }
bool SandboxedCRC4(sandbox2::Comms* comms, uint32_t* crc4) { bool SandboxedCRC4(sandbox2::Comms* comms, uint32_t* crc4) {
std::string input(absl::GetFlag(FLAGS_input)); const std::string input = absl::GetFlag(FLAGS_input);
const uint8_t* buf = reinterpret_cast<const uint8_t*>(input.data()); const uint8_t* buf = reinterpret_cast<const uint8_t*>(input.data());
size_t buf_size = input.size(); size_t buf_size = input.size();

View File

@ -27,6 +27,7 @@ cc_binary(
copts = sapi_platform_copts(), copts = sapi_platform_copts(),
data = [":custom_fork_bin"], data = [":custom_fork_bin"],
deps = [ deps = [
"//sandboxed_api:config",
"//sandboxed_api/sandbox2", "//sandboxed_api/sandbox2",
"//sandboxed_api/sandbox2:comms", "//sandboxed_api/sandbox2:comms",
"//sandboxed_api/sandbox2:forkserver", "//sandboxed_api/sandbox2:forkserver",

View File

@ -26,6 +26,7 @@
#include <glog/logging.h> #include <glog/logging.h>
#include "sandboxed_api/util/flag.h" #include "sandboxed_api/util/flag.h"
#include "absl/memory/memory.h" #include "absl/memory/memory.h"
#include "sandboxed_api/config.h"
#include "sandboxed_api/sandbox2/comms.h" #include "sandboxed_api/sandbox2/comms.h"
#include "sandboxed_api/sandbox2/executor.h" #include "sandboxed_api/sandbox2/executor.h"
#include "sandboxed_api/sandbox2/forkserver.h" #include "sandboxed_api/sandbox2/forkserver.h"
@ -37,9 +38,10 @@
#include "sandboxed_api/util/runfiles.h" #include "sandboxed_api/util/runfiles.h"
std::unique_ptr<sandbox2::Policy> GetPolicy() { std::unique_ptr<sandbox2::Policy> GetPolicy() {
return sandbox2::PolicyBuilder() sandbox2::PolicyBuilder builder;
// The most frequent syscall should go first in this sequence (to make it builder
// fast). // The most frequent syscall should go first in this
// sequence (to make it fast).
.AllowRead() .AllowRead()
.AllowWrite() .AllowWrite()
.AllowExit() .AllowExit()
@ -47,15 +49,14 @@ std::unique_ptr<sandbox2::Policy> GetPolicy() {
.AllowSyscalls({ .AllowSyscalls({
__NR_close, __NR_getpid, __NR_close, __NR_getpid,
#if defined(__NR_arch_prctl) #if defined(__NR_arch_prctl)
// Not defined with every CPU architecture in Prod. // Not defined with every CPU architecture in prod.
__NR_arch_prctl, __NR_arch_prctl,
#endif // defined(__NR_arch_prctl)
})
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
defined(THREAD_SANITIZER)
.AllowMmap()
#endif #endif
.BuildOrDie(); });
if constexpr (sapi::sanitizers::IsAny()) {
builder.AllowMmap();
}
return builder.BuildOrDie();
} }
static int SandboxIteration(sandbox2::ForkClient* fork_client, int32_t i) { static int SandboxIteration(sandbox2::ForkClient* fork_client, int32_t i) {
@ -68,14 +69,9 @@ static int SandboxIteration(sandbox2::ForkClient* fork_client, int32_t i) {
->limits() ->limits()
// Remove restrictions on the size of address-space of sandboxed // Remove restrictions on the size of address-space of sandboxed
// processes. Here, it's 1GiB. // processes. Here, it's 1GiB.
->set_rlimit_as( ->set_rlimit_as(sapi::sanitizers::IsAny() ? RLIM64_INFINITY
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \ : 1ULL << 30 // 1GiB
defined(THREAD_SANITIZER) )
RLIM64_INFINITY
#else
1ULL << 30 // 1GiB
#endif
)
// Kill sandboxed processes with a signal (SIGXFSZ) if it writes more than // Kill sandboxed processes with a signal (SIGXFSZ) if it writes more than
// these many bytes to the file-system (including logs in prod, which // these many bytes to the file-system (including logs in prod, which
// write to files STDOUT and STDERR). // write to files STDOUT and STDERR).
@ -84,15 +80,12 @@ static int SandboxIteration(sandbox2::ForkClient* fork_client, int32_t i) {
.set_rlimit_cpu(10 /* CPU-seconds */) .set_rlimit_cpu(10 /* CPU-seconds */)
.set_walltime_limit(absl::Seconds(5)); .set_walltime_limit(absl::Seconds(5));
auto* comms = executor->ipc()->comms(); sandbox2::Sandbox2 s2(std::move(executor), GetPolicy());
auto policy = GetPolicy();
sandbox2::Sandbox2 s2(std::move(executor), std::move(policy));
// Let the sandboxee run (asynchronously). // Let the sandboxee run (asynchronously).
CHECK(s2.RunAsync()); CHECK(s2.RunAsync());
// Send integer, which will be returned as the sandboxee's exit code. // Send integer, which will be returned as the sandboxee's exit code.
CHECK(comms->SendInt32(i)); CHECK(s2.comms()->SendInt32(i));
auto result = s2.AwaitResult(); auto result = s2.AwaitResult();
LOG(INFO) << "Final execution status of PID " << s2.GetPid() << ": " LOG(INFO) << "Final execution status of PID " << s2.GetPid() << ": "
@ -111,10 +104,9 @@ int main(int argc, char** argv) {
// This test is incompatible with sanitizers. // This test is incompatible with sanitizers.
// The `SKIP_SANITIZERS_AND_COVERAGE` macro won't work for us here since we // The `SKIP_SANITIZERS_AND_COVERAGE` macro won't work for us here since we
// need to return something. // need to return something.
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \ if constexpr (sapi::sanitizers::IsAny()) {
defined(THREAD_SANITIZER) return EXIT_SUCCESS;
return EXIT_SUCCESS; }
#endif
// Start a custom fork-server (via sandbox2::Executor). // Start a custom fork-server (via sandbox2::Executor).
// Note: In your own code, use sapi::GetDataDependencyFilePath() instead. // Note: In your own code, use sapi::GetDataDependencyFilePath() instead.

View File

@ -29,6 +29,7 @@ cc_binary(
copts = sapi_platform_copts(), copts = sapi_platform_copts(),
data = [":network_bin"], data = [":network_bin"],
deps = [ deps = [
"//sandboxed_api:config",
"//sandboxed_api/sandbox2", "//sandboxed_api/sandbox2",
"//sandboxed_api/sandbox2:comms", "//sandboxed_api/sandbox2:comms",
"//sandboxed_api/sandbox2/util:bpf_helper", "//sandboxed_api/sandbox2/util:bpf_helper",

View File

@ -30,6 +30,7 @@
#include <glog/logging.h> #include <glog/logging.h>
#include "absl/base/macros.h" #include "absl/base/macros.h"
#include "sandboxed_api/util/flag.h" #include "sandboxed_api/util/flag.h"
#include "sandboxed_api/config.h"
#include "sandboxed_api/sandbox2/comms.h" #include "sandboxed_api/sandbox2/comms.h"
#include "sandboxed_api/sandbox2/executor.h" #include "sandboxed_api/sandbox2/executor.h"
#include "sandboxed_api/sandbox2/policy.h" #include "sandboxed_api/sandbox2/policy.h"
@ -143,7 +144,7 @@ int ConnectToServer(int port) {
} }
bool HandleSandboxee(sandbox2::Comms* comms, int port) { bool HandleSandboxee(sandbox2::Comms* comms, int port) {
// connect to the server and pass the file descriptor to sandboxee. // Connect to the server and pass the file descriptor to sandboxee.
int client = ConnectToServer(port); int client = ConnectToServer(port);
if (client <= 0) { if (client <= 0) {
LOG(ERROR) << "connect_to_server() failed"; LOG(ERROR) << "connect_to_server() failed";
@ -165,10 +166,9 @@ int main(int argc, char** argv) {
// This test is incompatible with sanitizers. // This test is incompatible with sanitizers.
// The `SKIP_SANITIZERS_AND_COVERAGE` macro won't work for us here since we // The `SKIP_SANITIZERS_AND_COVERAGE` macro won't work for us here since we
// need to return something. // need to return something.
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \ if constexpr (sapi::sanitizers::IsAny()) {
defined(THREAD_SANITIZER) return EXIT_SUCCESS;
return EXIT_SUCCESS; }
#endif
if (getenv("COVERAGE") != nullptr) { if (getenv("COVERAGE") != nullptr) {
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -25,6 +25,7 @@ cc_binary(
copts = sapi_platform_copts(), copts = sapi_platform_copts(),
data = [":networkproxy_bin"], data = [":networkproxy_bin"],
deps = [ deps = [
"//sandboxed_api:config",
"//sandboxed_api/sandbox2", "//sandboxed_api/sandbox2",
"//sandboxed_api/sandbox2:comms", "//sandboxed_api/sandbox2:comms",
"//sandboxed_api/sandbox2/util:bpf_helper", "//sandboxed_api/sandbox2/util:bpf_helper",

View File

@ -18,6 +18,7 @@
#include <glog/logging.h> #include <glog/logging.h>
#include "absl/base/macros.h" #include "absl/base/macros.h"
#include "sandboxed_api/util/flag.h" #include "sandboxed_api/util/flag.h"
#include "sandboxed_api/config.h"
#include "sandboxed_api/sandbox2/comms.h" #include "sandboxed_api/sandbox2/comms.h"
#include "sandboxed_api/sandbox2/executor.h" #include "sandboxed_api/sandbox2/executor.h"
#include "sandboxed_api/sandbox2/policy.h" #include "sandboxed_api/sandbox2/policy.h"
@ -35,8 +36,8 @@ constexpr char kSandboxeePath[] =
"sandbox2/examples/network_proxy/networkproxy_bin"; "sandbox2/examples/network_proxy/networkproxy_bin";
std::unique_ptr<sandbox2::Policy> GetPolicy(absl::string_view sandboxee_path) { std::unique_ptr<sandbox2::Policy> GetPolicy(absl::string_view sandboxee_path) {
sandbox2::PolicyBuilder policy; sandbox2::PolicyBuilder builder;
policy.AllowExit() builder.AllowExit()
.AllowMmap() .AllowMmap()
.AllowRead() .AllowRead()
.AllowWrite() .AllowWrite()
@ -49,11 +50,11 @@ std::unique_ptr<sandbox2::Policy> GetPolicy(absl::string_view sandboxee_path) {
.AllowTcMalloc() .AllowTcMalloc()
.AddLibrariesForBinary(sandboxee_path); .AddLibrariesForBinary(sandboxee_path);
if (absl::GetFlag(FLAGS_connect_with_handler)) { if (absl::GetFlag(FLAGS_connect_with_handler)) {
policy.AddNetworkProxyHandlerPolicy(); builder.AddNetworkProxyHandlerPolicy();
} else { } else {
policy.AddNetworkProxyPolicy(); builder.AddNetworkProxyPolicy();
} }
return policy.AllowIPv6("::1").BuildOrDie(); return builder.AllowIPv6("::1").BuildOrDie();
} }
void Server(int port) { void Server(int port) {
@ -115,10 +116,9 @@ int main(int argc, char** argv) {
// This test is incompatible with sanitizers. // This test is incompatible with sanitizers.
// The `SKIP_SANITIZERS_AND_COVERAGE` macro won't work for us here since we // The `SKIP_SANITIZERS_AND_COVERAGE` macro won't work for us here since we
// need to return something. // need to return something.
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \ if constexpr (sapi::sanitizers::IsAny()) {
defined(THREAD_SANITIZER) return EXIT_SUCCESS;
return EXIT_SUCCESS; }
#endif
if (getenv("COVERAGE") != nullptr) { if (getenv("COVERAGE") != nullptr) {
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -30,6 +30,7 @@ cc_binary(
copts = sapi_platform_copts(), copts = sapi_platform_copts(),
data = [":static_bin"], data = [":static_bin"],
deps = [ deps = [
"//sandboxed_api:config",
"//sandboxed_api/sandbox2", "//sandboxed_api/sandbox2",
"//sandboxed_api/sandbox2/util:bpf_helper", "//sandboxed_api/sandbox2/util:bpf_helper",
"//sandboxed_api/util:flags", "//sandboxed_api/util:flags",

View File

@ -30,6 +30,7 @@
#include <glog/logging.h> #include <glog/logging.h>
#include "sandboxed_api/util/flag.h" #include "sandboxed_api/util/flag.h"
#include "absl/memory/memory.h" #include "absl/memory/memory.h"
#include "sandboxed_api/config.h"
#include "sandboxed_api/sandbox2/executor.h" #include "sandboxed_api/sandbox2/executor.h"
#include "sandboxed_api/sandbox2/limits.h" #include "sandboxed_api/sandbox2/limits.h"
#include "sandboxed_api/sandbox2/policy.h" #include "sandboxed_api/sandbox2/policy.h"
@ -101,10 +102,9 @@ int main(int argc, char** argv) {
// This test is incompatible with sanitizers. // This test is incompatible with sanitizers.
// The `SKIP_SANITIZERS_AND_COVERAGE` macro won't work for us here since we // The `SKIP_SANITIZERS_AND_COVERAGE` macro won't work for us here since we
// need to return something. // need to return something.
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \ if constexpr (sapi::sanitizers::IsAny()) {
defined(THREAD_SANITIZER) return EXIT_SUCCESS;
return EXIT_SUCCESS; }
#endif
gflags::ParseCommandLineFlags(&argc, &argv, true); gflags::ParseCommandLineFlags(&argc, &argv, true);
google::InitGoogleLogging(argv[0]); google::InitGoogleLogging(argv[0]);

View File

@ -193,20 +193,19 @@ PolicyBuilder& PolicyBuilder::AllowSystemMalloc() {
} }
PolicyBuilder& PolicyBuilder::AllowLlvmSanitizers() { PolicyBuilder& PolicyBuilder::AllowLlvmSanitizers() {
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \ if constexpr (sapi::sanitizers::IsAny()) {
defined(THREAD_SANITIZER) AddPolicyOnSyscall(__NR_madvise, {
AddPolicyOnSyscall(__NR_madvise, { ARG_32(2),
ARG_32(2), JEQ32(MADV_DONTDUMP, ALLOW),
JEQ32(MADV_DONTDUMP, ALLOW), JEQ32(MADV_NOHUGEPAGE, ALLOW),
JEQ32(MADV_NOHUGEPAGE, ALLOW), });
}); // Sanitizers read from /proc. For example:
// Sanitizers read from /proc. For example: // https://github.com/llvm-mirror/compiler-rt/blob/69445f095c22aac2388f939bedebf224a6efcdaf/lib/sanitizer_common/sanitizer_linux.cpp#L1101
// https://github.com/llvm-mirror/compiler-rt/blob/69445f095c22aac2388f939bedebf224a6efcdaf/lib/sanitizer_common/sanitizer_linux.cpp#L1101 AddDirectory("/proc");
AddDirectory("/proc"); }
#endif if constexpr (sapi::sanitizers::IsASan()) {
#if defined(ADDRESS_SANITIZER) AllowSyscall(__NR_sigaltstack);
AllowSyscall(__NR_sigaltstack); }
#endif
return *this; return *this;
} }

View File

@ -29,6 +29,7 @@
#include "absl/strings/match.h" #include "absl/strings/match.h"
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#include "absl/strings/str_split.h" #include "absl/strings/str_split.h"
#include "sandboxed_api/config.h"
#include "sandboxed_api/sandbox2/comms.h" #include "sandboxed_api/sandbox2/comms.h"
#include "sandboxed_api/sandbox2/executor.h" #include "sandboxed_api/sandbox2/executor.h"
#include "sandboxed_api/sandbox2/ipc.h" #include "sandboxed_api/sandbox2/ipc.h"
@ -166,10 +167,9 @@ std::string PolicyBuilderTest::Run(std::vector<std::string> args,
} }
auto executor = absl::make_unique<sandbox2::Executor>(args[0], args); auto executor = absl::make_unique<sandbox2::Executor>(args[0], args);
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \ if constexpr (sapi::sanitizers::IsAny()) {
defined(THREAD_SANITIZER) executor->limits()->set_rlimit_as(RLIM64_INFINITY);
executor->limits()->set_rlimit_as(RLIM64_INFINITY); }
#endif
int fd1 = executor->ipc()->ReceiveFd(STDOUT_FILENO); int fd1 = executor->ipc()->ReceiveFd(STDOUT_FILENO);
sandbox2::Sandbox2 s2(std::move(executor), builder.BuildOrDie()); sandbox2::Sandbox2 s2(std::move(executor), builder.BuildOrDie());

View File

@ -18,6 +18,7 @@
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h" #include "absl/strings/str_join.h"
#include "sandboxed_api/config.h"
#include "sandboxed_api/sandbox2/syscall.h" #include "sandboxed_api/sandbox2/syscall.h"
#include "sandboxed_api/sandbox2/util.h" #include "sandboxed_api/sandbox2/util.h"
@ -109,21 +110,20 @@ std::string Result::ToString() const {
result = result =
absl::StrCat("<UNKNOWN>(", final_status(), ") Code: ", reason_code()); absl::StrCat("<UNKNOWN>(", final_status(), ") Code: ", reason_code());
} }
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \ if constexpr (sapi::sanitizers::IsAny()) {
defined(THREAD_SANITIZER) absl::StrAppend(
absl::StrAppend(&result, &result,
" - Warning: this executor is built with ASAN, " " - Warning: this executor is built with ASAN, MSAN or TSAN, chances "
"MSAN or TSAN, chances are the sandboxee too, which is " "are the sandboxee is too, which is incompatible with sandboxing.");
"incompatible with sandboxing."); } else {
#else if (
if ( getenv("COVERAGE") != nullptr) {
getenv("COVERAGE") != nullptr) { absl::StrAppend(
absl::StrAppend(&result, &result,
" - Warning: this executor is built with coverage " " - Warning: this executor is built with coverage enabled, chances "
"enabled, chances are the sandboxee too, which is " "are the sandboxee too, which is incompatible with sandboxing.");
"incompatible with sandboxing."); }
} }
#endif
return result; return result;
} }

View File

@ -291,21 +291,13 @@ std::vector<std::string> GetStackTrace(const Regs* regs, const Mounts& mounts) {
return {"[ERROR (noregs)]"}; return {"[ERROR (noregs)]"};
} }
#if defined(THREAD_SANITIZER) || defined(ADDRESS_SANITIZER) || \
defined(MEMORY_SANITIZER)
constexpr bool kSanitizerEnabled = true;
#else
constexpr bool kSanitizerEnabled = false;
#endif
const bool coverage_enabled =
getenv("COVERAGE");
// Show a warning if sandboxed libunwind is requested but we're running in // Show a warning if sandboxed libunwind is requested but we're running in
// an ASAN / coverage build (= we can't use sandboxed libunwind). // an ASAN/coverage build (= we can't use sandboxed libunwind).
if (absl::GetFlag(FLAGS_sandbox_libunwind_crash_handler) && if (const bool coverage_enabled =
(kSanitizerEnabled || coverage_enabled)) { getenv("COVERAGE") != nullptr;
LOG_IF(WARNING, kSanitizerEnabled) absl::GetFlag(FLAGS_sandbox_libunwind_crash_handler) &&
(sapi::sanitizers::IsAny() || coverage_enabled)) {
LOG_IF(WARNING, sapi::sanitizers::IsAny())
<< "Sanitizer build, using non-sandboxed libunwind"; << "Sanitizer build, using non-sandboxed libunwind";
LOG_IF(WARNING, coverage_enabled) LOG_IF(WARNING, coverage_enabled)
<< "Coverage build, using non-sandboxed libunwind"; << "Coverage build, using non-sandboxed libunwind";

View File

@ -25,17 +25,18 @@
#include "sandboxed_api/examples/sum/lib/sandbox.h" #include "sandboxed_api/examples/sum/lib/sandbox.h"
#include "sandboxed_api/examples/sum/lib/sum-sapi.sapi.h" #include "sandboxed_api/examples/sum/lib/sum-sapi.sapi.h"
#include "sandboxed_api/examples/sum/lib/sum-sapi_embed.h" #include "sandboxed_api/examples/sum/lib/sum-sapi_embed.h"
#include "sandboxed_api/testing.h"
#include "sandboxed_api/transaction.h" #include "sandboxed_api/transaction.h"
#include "sandboxed_api/util/status_matchers.h" #include "sandboxed_api/util/status_matchers.h"
namespace sapi {
namespace {
using ::sapi::IsOk; using ::sapi::IsOk;
using ::sapi::StatusIs; using ::sapi::StatusIs;
using ::testing::Eq; using ::testing::Eq;
using ::testing::HasSubstr; using ::testing::HasSubstr;
namespace sapi {
namespace {
// Functions that will be used during the benchmarks: // Functions that will be used during the benchmarks:
// Function causing no load in the sandboxee. // Function causing no load in the sandboxee.
@ -134,7 +135,9 @@ void BenchmarkIntDataSynchronization(benchmark::State& state) {
BENCHMARK(BenchmarkIntDataSynchronization); BENCHMARK(BenchmarkIntDataSynchronization);
// Test whether stack trace generation works. // Test whether stack trace generation works.
TEST(SAPITest, HasStackTraces) { TEST(SapiTest, HasStackTraces) {
SKIP_SANITIZERS_AND_COVERAGE;
auto sandbox = absl::make_unique<StringopSandbox>(); auto sandbox = absl::make_unique<StringopSandbox>();
ASSERT_THAT(sandbox->Init(), IsOk()); ASSERT_THAT(sandbox->Init(), IsOk());
StringopApi api(sandbox.get()); StringopApi api(sandbox.get());

View File

@ -40,16 +40,17 @@
// //
// The downside of this approach is that no coverage will be collected. // The downside of this approach is that no coverage will be collected.
// To still have coverage, pre-compile sandboxees and add them as test data, // To still have coverage, pre-compile sandboxees and add them as test data,
// then no need to skip tests. // then there will be no need to skip tests.
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \ #if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
defined(THREAD_SANITIZER) defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)
#define SKIP_SANITIZERS_AND_COVERAGE return #define SKIP_SANITIZERS_AND_COVERAGE return
#else #else
#define SKIP_SANITIZERS_AND_COVERAGE \ #define SAPI_BUILDDATA_COVERAGE_ENABLED false
do { \ #define SKIP_SANITIZERS_AND_COVERAGE \
if (getenv("COVERAGE") != nullptr) { \ do { \
return; \ if (SAPI_BUILDDATA_COVERAGE_ENABLED || getenv("COVERAGE") != nullptr) { \
} \ return; \
} \
} while (0) } while (0)
#endif #endif