Decouple sandboxed stack tracing

This allows to split monitor & stack_trace related targets.
Also move stack traces related functionality into MonitorBase.

PiperOrigin-RevId: 510112916
Change-Id: I60eabf9c9b3204dc369713edd8ae05fded306875
This commit is contained in:
Wiktor Garbacz 2023-02-16 05:06:50 -08:00 committed by Copybara-Service
parent d2dbbbae76
commit 71692bb50b
9 changed files with 303 additions and 117 deletions

View File

@ -308,11 +308,7 @@ cc_library(
cc_library(
name = "sandbox2",
srcs = [
"monitor_ptrace.cc",
"monitor_ptrace.h",
"sandbox2.cc",
"stack_trace.cc",
"stack_trace.h",
],
hdrs = [
"client.h",
@ -337,6 +333,7 @@ cc_library(
":limits",
":logsink",
":monitor_base",
":monitor_ptrace",
":mounts",
":namespace",
":notify",
@ -344,39 +341,88 @@ cc_library(
":policybuilder",
":regs",
":result",
":sanitizer",
":stack_trace",
":syscall",
":util",
":violation_cc_proto",
"//sandboxed_api:config",
"//sandboxed_api/sandbox2/network_proxy:client",
"//sandboxed_api/sandbox2/network_proxy:filtering",
"//sandboxed_api/util:fileops",
"@com_google_absl//absl/base",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/log",
"@com_google_absl//absl/log:check",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/time",
"@com_google_absl//absl/types:optional",
"@com_google_absl//absl/types:span",
],
)
cc_library(
name = "stack_trace",
srcs = ["stack_trace.cc"],
hdrs = ["stack_trace.h"],
copts = sapi_platform_copts(),
deps = [
":comms",
":executor",
":limits",
":namespace",
":policy",
":policybuilder",
":regs",
":result",
"//sandboxed_api:config",
"//sandboxed_api/sandbox2/unwind",
"//sandboxed_api/sandbox2/unwind:unwind_cc_proto",
"//sandboxed_api/sandbox2/util:bpf_helper",
"//sandboxed_api/util:file_base",
"//sandboxed_api/util:file_helpers",
"//sandboxed_api/util:fileops",
"//sandboxed_api/util:raw_logging",
"//sandboxed_api/util:status",
"//sandboxed_api/util:strerror",
"//sandboxed_api/util:temp_file",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/cleanup",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/flags:flag",
"@com_google_absl//absl/log",
"@com_google_absl//absl/log:check",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
],
)
cc_library(
name = "monitor_ptrace",
srcs = ["monitor_ptrace.cc"],
hdrs = ["monitor_ptrace.h"],
copts = sapi_platform_copts(),
deps = [
":client",
":comms",
":executor",
":monitor_base",
":notify",
":policy",
":regs",
":result",
":sanitizer",
":syscall",
":util",
"//sandboxed_api:config",
"//sandboxed_api/util:raw_logging",
"//sandboxed_api/util:status",
"@com_google_absl//absl/cleanup",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/flags:flag",
"@com_google_absl//absl/status",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/synchronization",
"@com_google_absl//absl/time",
"@com_google_absl//absl/types:optional",
"@com_google_absl//absl/types:span",
"@org_kernel_libcap//:libcap",
],
)
@ -396,7 +442,9 @@ cc_library(
":namespace",
":notify",
":policy",
":regs",
":result",
":stack_trace",
":syscall",
":util",
"//sandboxed_api/sandbox2/network_proxy:server",
@ -404,6 +452,7 @@ cc_library(
"//sandboxed_api/util:raw_logging",
"//sandboxed_api/util:strerror",
"//sandboxed_api/util:temp_file",
"@com_google_absl//absl/base",
"@com_google_absl//absl/cleanup",
"@com_google_absl//absl/flags:flag",
"@com_google_absl//absl/log",
@ -891,7 +940,6 @@ cc_test(
cc_test(
name = "stack_trace_test",
srcs = [
"stack_trace.h",
"stack_trace_test.cc",
],
copts = sapi_platform_copts(),
@ -902,6 +950,7 @@ cc_test(
":namespace",
":regs",
":sandbox2",
":stack_trace",
"//sandboxed_api:testing",
"//sandboxed_api/sandbox2/util:bpf_helper",
"//sandboxed_api/util:fileops",

View File

@ -295,25 +295,19 @@ add_library(sandbox2_sandbox2 ${SAPI_LIB_TYPE}
add_library(sandbox2::sandbox2 ALIAS sandbox2_sandbox2)
target_link_libraries(sandbox2_sandbox2
PRIVATE absl::core_headers
absl::cleanup
absl::flat_hash_set
absl::memory
absl::optional
absl::str_format
absl::strings
sapi::strerror
sapi::base
PUBLIC absl::flat_hash_map
absl::status
absl::statusor
absl::synchronization
absl::time
sapi::config
sapi::file_base
sapi::fileops
sapi::status
sapi::temp_file
sandbox2::bpf_helper
sandbox2::client
sandbox2::comms
sandbox2::executor
@ -323,6 +317,7 @@ target_link_libraries(sandbox2_sandbox2
sandbox2::limits
sandbox2::logsink
sandbox2::monitor_base
sandbox2::monitor_ptrace
sandbox2::mounts
sandbox2::mount_tree_proto
sandbox2::namespace
@ -333,14 +328,47 @@ target_link_libraries(sandbox2_sandbox2
sandbox2::policybuilder
sandbox2::regs
sandbox2::result
sandbox2::sanitizer
sandbox2::syscall
sandbox2::unwind
sandbox2::unwind_proto
sandbox2::util
sandbox2::violation_proto
)
# sandboxed_api/sandbox2:stack_trace
add_library(sandbox2_stack_trace ${SAPI_LIB_TYPE}
stack_trace.cc
stack_trace.h
)
add_library(sandbox2::stack_trace ALIAS sandbox2_stack_trace)
target_link_libraries(sandbox2_stack_trace
PRIVATE absl::cleanup
absl::flags
absl::log
absl::memory
absl::status
absl::strings
sandbox2::client
sandbox2::limits
sandbox2::policybuilder
sandbox2::util
sandbox2::unwind
sandbox2::unwind_proto
sapi::base
sapi::config
sapi::file_base
sapi::fileops
sapi::raw_logging
sapi::status
PUBLIC absl::statusor
sandbox2::comms
sandbox2::executor
sandbox2::namespace
sandbox2::policy
sandbox2::result
sandbox2::regs
)
# sandboxed_api/sandbox2:monitor_base
add_library(sandbox2_monitor_base ${SAPI_LIB_TYPE}
monitor_base.cc
@ -355,6 +383,7 @@ target_link_libraries(sandbox2_monitor_base
sandbox2::limits
sandbox2::mounts
sandbox2::namespace
sandbox2::stack_trace
sandbox2::util
sapi::file_helpers
sapi::temp_file
@ -373,6 +402,38 @@ target_link_libraries(sandbox2_monitor_base
sandbox2::syscall
)
# sandboxed_api/sandbox2:monitor_ptrace
add_library(sandbox2_monitor_ptrace ${SAPI_LIB_TYPE}
monitor_ptrace.cc
monitor_ptrace.h
)
add_library(sandbox2::monitor_ptrace ALIAS sandbox2_monitor_ptrace)
target_link_libraries(sandbox2_monitor_ptrace
PRIVATE absl::cleanup
absl::flat_hash_set
absl::flags
absl::status
absl::strings
absl::time
sapi::base
sapi::config
sapi::status
sandbox2::client
sandbox2::comms
sandbox2::result
sandbox2::sanitizer
sandbox2::util
PUBLIC sandbox2::executor
sandbox2::monitor_base
sandbox2::notify
sandbox2::policy
sandbox2::regs
sandbox2::syscall
absl::synchronization
absl::flat_hash_map
sapi::raw_logging
)
# sandboxed_api/sandbox2:policybuilder
add_library(sandbox2_policybuilder ${SAPI_LIB_TYPE}
policybuilder.cc
@ -1001,6 +1062,7 @@ if(BUILD_TESTING AND SAPI_BUILD_TESTING)
sandbox2::global_forkserver
sandbox2::namespace
sandbox2::sandbox2
sandbox2::stack_trace
sandbox2::util
sapi::fileops
sapi::temp_file

View File

@ -44,6 +44,7 @@
#include "sandboxed_api/sandbox2/network_proxy/server.h"
#include "sandboxed_api/sandbox2/policy.h"
#include "sandboxed_api/sandbox2/result.h"
#include "sandboxed_api/sandbox2/stack_trace.h"
#include "sandboxed_api/sandbox2/syscall.h"
#include "sandboxed_api/sandbox2/util.h"
#include "sandboxed_api/util/file_helpers.h"
@ -60,6 +61,8 @@ ABSL_FLAG(bool, sandbox2_report_on_sandboxee_timeout, true,
ABSL_DECLARE_FLAG(bool, sandbox2_danger_danger_permit_all);
ABSL_DECLARE_FLAG(std::string, sandbox2_danger_danger_permit_all_and_log);
ABSL_DECLARE_FLAG(bool, sandbox_libunwind_crash_handler);
namespace sandbox2 {
namespace {
@ -118,7 +121,8 @@ MonitorBase::MonitorBase(Executor* executor, Policy* policy, Notify* notify)
policy_(policy),
// NOLINTNEXTLINE clang-diagnostic-deprecated-declarations
comms_(executor_->ipc()->comms()),
ipc_(executor_->ipc()) {
ipc_(executor_->ipc()),
uses_custom_forkserver_(executor_->fork_client_ != nullptr) {
// It's a pre-connected Comms channel, no need to accept new connection.
CHECK(comms_->IsConnected());
std::string path =
@ -383,6 +387,20 @@ void MonitorBase::LogSyscallViolationExplanation(const Syscall& syscall) const {
}
}
bool MonitorBase::StackTraceCollectionPossible() const {
// Only get the stacktrace if we are not in the libunwind sandbox (avoid
// recursion).
if ((policy_->GetNamespace() ||
absl::GetFlag(FLAGS_sandbox_libunwind_crash_handler) == false) &&
executor_->libunwind_sbox_for_pid_ == 0) {
return true;
}
LOG(ERROR) << "Cannot collect stack trace. Unwind pid "
<< executor_->libunwind_sbox_for_pid_ << ", namespace "
<< policy_->GetNamespace();
return false;
}
void MonitorBase::EnableNetworkProxyServer() {
int fd = ipc_->ReceiveFd(NetworkProxyClient::kFDName);
@ -392,4 +410,46 @@ void MonitorBase::EnableNetworkProxyServer() {
network_proxy_thread_ = std::thread(&NetworkProxyServer::Run,
network_proxy_server_.get());
}
bool MonitorBase::ShouldCollectStackTrace(Result::StatusEnum status) const {
if (!StackTraceCollectionPossible()) {
return false;
}
switch (status) {
case Result::EXTERNAL_KILL:
return policy_->collect_stacktrace_on_kill_;
case Result::TIMEOUT:
return policy_->collect_stacktrace_on_timeout_;
case Result::SIGNALED:
return policy_->collect_stacktrace_on_signal_;
case Result::VIOLATION:
return policy_->collect_stacktrace_on_violation_;
case Result::OK:
return policy_->collect_stacktrace_on_exit_;
default:
return false;
}
}
absl::StatusOr<std::vector<std::string>> MonitorBase::GetStackTrace(
const Regs* regs) {
return sandbox2::GetStackTrace(regs, policy_->GetNamespace(),
uses_custom_forkserver_);
}
absl::StatusOr<std::vector<std::string>> MonitorBase::GetAndLogStackTrace(
const Regs* regs) {
auto stack_trace = GetStackTrace(regs);
if (!stack_trace.ok()) {
return stack_trace.status();
}
LOG(INFO) << "Stack trace: [";
for (const auto& frame : CompactStackTrace(*stack_trace)) {
LOG(INFO) << " " << frame;
}
LOG(INFO) << "]";
return stack_trace;
}
} // namespace sandbox2

View File

@ -24,6 +24,8 @@
#include <cstdio>
#include <memory>
#include <thread>
#include <string>
#include <vector>
#include "absl/status/statusor.h"
#include "absl/synchronization/notification.h"
@ -34,6 +36,7 @@
#include "sandboxed_api/sandbox2/network_proxy/server.h"
#include "sandboxed_api/sandbox2/notify.h"
#include "sandboxed_api/sandbox2/policy.h"
#include "sandboxed_api/sandbox2/regs.h"
#include "sandboxed_api/sandbox2/result.h"
#include "sandboxed_api/sandbox2/syscall.h"
@ -78,6 +81,19 @@ class MonitorBase {
// explanation for the reason of the violation.
void LogSyscallViolation(const Syscall& syscall) const;
// Tells if collecting stack trace is at all possible.
bool StackTraceCollectionPossible() const;
// Whether a stack trace should be collected given the current status
bool ShouldCollectStackTrace(Result::StatusEnum status) const;
// Gets stack trace.
absl::StatusOr<std::vector<std::string>> GetStackTrace(const Regs* regs);
// Gets and logs stack trace.
absl::StatusOr<std::vector<std::string>> GetAndLogStackTrace(
const Regs* regs);
// Internal objects, owned by the Sandbox2 object.
Executor* executor_;
Notify* notify_;
@ -134,6 +150,9 @@ class MonitorBase {
std::string comms_fd_dev_;
std::thread network_proxy_thread_;
// Is the sandboxee forked from a custom forkserver?
bool uses_custom_forkserver_;
};
} // namespace sandbox2

View File

@ -46,7 +46,6 @@
#include "sandboxed_api/sandbox2/regs.h"
#include "sandboxed_api/sandbox2/result.h"
#include "sandboxed_api/sandbox2/sanitizer.h"
#include "sandboxed_api/sandbox2/stack_trace.h"
#include "sandboxed_api/sandbox2/syscall.h"
#include "sandboxed_api/sandbox2/util.h"
#include "sandboxed_api/util/raw_logging.h"
@ -63,7 +62,6 @@ ABSL_FLAG(absl::Duration, sandbox2_stack_traces_collection_timeout,
"traces is enabled.");
ABSL_DECLARE_FLAG(bool, sandbox2_danger_danger_permit_all);
ABSL_DECLARE_FLAG(bool, sandbox_libunwind_crash_handler);
namespace sandbox2 {
namespace {
@ -178,8 +176,7 @@ void CompleteSyscall(pid_t pid, int signo) {
PtraceMonitor::PtraceMonitor(Executor* executor, Policy* policy, Notify* notify)
: MonitorBase(executor, policy, notify),
wait_for_execve_(executor->enable_sandboxing_pre_execve_),
uses_custom_forkserver_(executor_->fork_client_ != nullptr) {
wait_for_execve_(executor->enable_sandboxing_pre_execve_) {
if (executor_->limits()->wall_time_limit() != absl::ZeroDuration()) {
auto deadline = absl::Now() + executor_->limits()->wall_time_limit();
deadline_millis_.store(absl::ToUnixMillis(deadline),
@ -196,62 +193,12 @@ bool PtraceMonitor::IsActivelyMonitoring() {
void PtraceMonitor::SetActivelyMonitoring() { wait_for_execve_ = false; }
bool PtraceMonitor::StackTraceCollectionPossible() const {
// Only get the stacktrace if we are not in the libunwind sandbox (avoid
// recursion).
if ((policy_->GetNamespace() ||
absl::GetFlag(FLAGS_sandbox_libunwind_crash_handler) == false) &&
executor_->libunwind_sbox_for_pid_ == 0) {
return true;
} else {
LOG(ERROR) << "Cannot collect stack trace. Unwind pid "
<< executor_->libunwind_sbox_for_pid_ << ", namespace "
<< policy_->GetNamespace();
return false;
}
}
bool PtraceMonitor::ShouldCollectStackTrace() const {
if (!StackTraceCollectionPossible()) {
return false;
}
switch (result_.final_status()) {
case Result::EXTERNAL_KILL:
return policy_->collect_stacktrace_on_kill_;
case Result::TIMEOUT:
return policy_->collect_stacktrace_on_timeout_;
case Result::SIGNALED:
return policy_->collect_stacktrace_on_signal_;
case Result::VIOLATION:
return policy_->collect_stacktrace_on_violation_;
case Result::OK:
return policy_->collect_stacktrace_on_exit_;
default:
return false;
}
}
absl::StatusOr<std::vector<std::string>> PtraceMonitor::GetAndLogStackTrace(
const Regs* regs) {
SAPI_ASSIGN_OR_RETURN(
std::vector<std::string> stack_trace,
GetStackTrace(regs, policy_->GetNamespace(), uses_custom_forkserver_));
LOG(INFO) << "Stack trace: [";
for (const auto& frame : CompactStackTrace(stack_trace)) {
LOG(INFO) << " " << frame;
}
LOG(INFO) << "]";
return stack_trace;
}
void PtraceMonitor::SetAdditionalResultInfo(std::unique_ptr<Regs> regs) {
pid_t pid = regs->pid();
result_.SetRegs(std::move(regs));
result_.SetProgName(util::GetProgName(pid));
result_.SetProcMaps(ReadProcMaps(pid));
if (!ShouldCollectStackTrace()) {
if (!ShouldCollectStackTrace(result_.final_status())) {
VLOG(1) << "Stack traces have been disabled";
return;
}
@ -970,8 +917,7 @@ void PtraceMonitor::StateProcessStopped(pid_t pid, int status) {
pid]() -> absl::StatusOr<std::vector<std::string>> {
Regs regs(pid);
SAPI_RETURN_IF_ERROR(regs.Fetch());
return GetStackTrace(&regs, policy_->GetNamespace(),
uses_custom_forkserver_);
return GetStackTrace(&regs);
}();
if (!stack_trace.ok()) {

View File

@ -25,7 +25,6 @@
#include <thread>
#include "absl/container/flat_hash_map.h"
#include "absl/status/statusor.h"
#include "absl/synchronization/mutex.h"
#include "absl/synchronization/notification.h"
#include "sandboxed_api/sandbox2/executor.h"
@ -33,7 +32,6 @@
#include "sandboxed_api/sandbox2/notify.h"
#include "sandboxed_api/sandbox2/policy.h"
#include "sandboxed_api/sandbox2/regs.h"
#include "sandboxed_api/sandbox2/result.h"
#include "sandboxed_api/sandbox2/syscall.h"
#include "sandboxed_api/util/raw_logging.h"
@ -89,12 +87,6 @@ class PtraceMonitor : public MonitorBase {
// Process with given PID changed state to a stopped state.
void StateProcessStopped(pid_t pid, int status);
// Tells if collecting stack trace is at all possible.
bool StackTraceCollectionPossible() const;
// Whether a stack trace should be collected given the current status
bool ShouldCollectStackTrace() const;
// Sets additional information in the result object, such as program name,
// stack trace etc.
void SetAdditionalResultInfo(std::unique_ptr<Regs> regs);
@ -103,10 +95,6 @@ class PtraceMonitor : public MonitorBase {
void ActionProcessSyscallViolation(Regs* regs, const Syscall& syscall,
ViolationType violation_type);
// Gets and logs stack trace.
absl::StatusOr<std::vector<std::string>> GetAndLogStackTrace(
const Regs* regs);
void LogStackTraceOfPid(pid_t pid);
// Ptrace events:
@ -166,8 +154,6 @@ class PtraceMonitor : public MonitorBase {
// Syscalls that are running, whose result values we want to inspect.
absl::flat_hash_map<pid_t, Syscall> syscalls_in_progress_;
sigset_t sset_;
// Is the sandboxee forked from a custom forkserver?
bool uses_custom_forkserver_;
// Monitor thread object.
std::unique_ptr<std::thread> thread_;

View File

@ -19,15 +19,45 @@
#include <csignal>
#include <memory>
#include <string>
#include <vector>
#include "absl/base/call_once.h"
#include "absl/log/check.h"
#include "absl/status/statusor.h"
#include "absl/time/time.h"
#include "sandboxed_api/sandbox2/monitor_base.h"
#include "sandboxed_api/sandbox2/monitor_ptrace.h"
#include "sandboxed_api/sandbox2/result.h"
#include "sandboxed_api/sandbox2/stack_trace.h"
namespace sandbox2 {
namespace {
class Sandbox2Peer : public internal::SandboxPeer {
public:
static std::unique_ptr<SandboxPeer> Spawn(std::unique_ptr<Executor> executor,
std::unique_ptr<Policy> policy) {
return std::make_unique<Sandbox2Peer>(std::move(executor),
std::move(policy));
}
Sandbox2Peer(std::unique_ptr<Executor> executor,
std::unique_ptr<Policy> policy)
: sandbox_(std::move(executor), std::move(policy)) {
sandbox_.RunAsync();
}
Comms* comms() override { return sandbox_.comms(); }
void Kill() override { sandbox_.Kill(); }
Result AwaitResult() override { return sandbox_.AwaitResult(); }
private:
Sandbox2 sandbox_;
};
} // namespace
absl::StatusOr<Result> Sandbox2::AwaitResultWithTimeout(
absl::Duration timeout) {
CHECK(monitor_ != nullptr) << "Sandbox was not launched yet";
@ -70,6 +100,11 @@ void Sandbox2::set_walltime_limit(absl::Duration limit) const {
}
void Sandbox2::Launch() {
static absl::once_flag init_sandbox_peer_flag;
absl::call_once(init_sandbox_peer_flag, []() {
internal::SandboxPeer::spawn_fn_ = Sandbox2Peer::Spawn;
});
monitor_ = std::make_unique<PtraceMonitor>(executor_.get(), policy_.get(),
notify_.get());
monitor_->Launch();

View File

@ -29,23 +29,18 @@
#include "absl/log/log.h"
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/strip.h"
#include "libcap/include/sys/capability.h"
#include "sandboxed_api/config.h"
#include "sandboxed_api/sandbox2/comms.h"
#include "sandboxed_api/sandbox2/executor.h"
#include "sandboxed_api/sandbox2/ipc.h"
#include "sandboxed_api/sandbox2/limits.h"
#include "sandboxed_api/sandbox2/policy.h"
#include "sandboxed_api/sandbox2/policybuilder.h"
#include "sandboxed_api/sandbox2/regs.h"
#include "sandboxed_api/sandbox2/result.h"
#include "sandboxed_api/sandbox2/sandbox2.h"
#include "sandboxed_api/sandbox2/unwind/unwind.h"
#include "sandboxed_api/sandbox2/unwind/unwind.pb.h"
#include "sandboxed_api/sandbox2/util/bpf_helper.h"
#include "sandboxed_api/util/fileops.h"
#include "sandboxed_api/util/path.h"
#include "sandboxed_api/util/raw_logging.h"
@ -79,7 +74,7 @@ class StackTracePeer {
const std::string& app_path, const std::string& exe_path,
const Namespace* ns, bool uses_custom_forkserver);
static absl::StatusOr<UnwindResult> LaunchLibunwindSandbox(
static absl::StatusOr<std::vector<std::string>> LaunchLibunwindSandbox(
const Regs* regs, const Namespace* ns, bool uses_custom_forkserver);
};
@ -163,7 +158,11 @@ absl::StatusOr<std::unique_ptr<Policy>> StackTracePeer::GetPolicy(
return std::move(policy);
}
absl::StatusOr<UnwindResult> StackTracePeer::LaunchLibunwindSandbox(
namespace internal {
SandboxPeer::SpawnFn SandboxPeer::spawn_fn_ = nullptr;
} // namespace internal
absl::StatusOr<std::vector<std::string>> StackTracePeer::LaunchLibunwindSandbox(
const Regs* regs, const Namespace* ns, bool uses_custom_forkserver) {
const pid_t pid = regs->pid();
@ -240,11 +239,11 @@ absl::StatusOr<UnwindResult> StackTracePeer::LaunchLibunwindSandbox(
std::unique_ptr<Policy> policy,
StackTracePeer::GetPolicy(pid, unwind_temp_maps_path, app_path, exe_path,
ns, uses_custom_forkserver));
Sandbox2 sandbox(std::move(executor), std::move(policy));
VLOG(1) << "Running libunwind sandbox";
sandbox.RunAsync();
Comms* comms = sandbox.comms();
auto sandbox =
internal::SandboxPeer::Spawn(std::move(executor), std::move(policy));
Comms* comms = sandbox->comms();
UnwindSetup msg;
msg.set_pid(pid);
@ -253,8 +252,8 @@ absl::StatusOr<UnwindResult> StackTracePeer::LaunchLibunwindSandbox(
msg.set_default_max_frames(kDefaultMaxFrames);
absl::Cleanup kill_sandbox = [&sandbox]() {
sandbox.Kill();
sandbox.AwaitResult().IgnoreResult();
sandbox->Kill();
sandbox->AwaitResult().IgnoreResult();
};
if (!comms->SendProtoBuf(msg)) {
@ -277,7 +276,7 @@ absl::StatusOr<UnwindResult> StackTracePeer::LaunchLibunwindSandbox(
std::move(kill_sandbox).Cancel();
auto sandbox_result = sandbox.AwaitResult();
auto sandbox_result = sandbox->AwaitResult();
LOG(INFO) << "Libunwind execution status: " << sandbox_result.ToString();
@ -287,7 +286,8 @@ absl::StatusOr<UnwindResult> StackTracePeer::LaunchLibunwindSandbox(
sandbox_result.ToString()));
}
return result;
return std::vector<std::string>(result.stacktrace().begin(),
result.stacktrace().end());
}
absl::StatusOr<std::vector<std::string>> GetStackTrace(
@ -317,11 +317,8 @@ absl::StatusOr<std::vector<std::string>> GetStackTrace(
return UnsafeGetStackTrace(regs->pid());
}
SAPI_ASSIGN_OR_RETURN(
UnwindResult res,
StackTracePeer::LaunchLibunwindSandbox(regs, ns, uses_custom_forkserver));
return std::vector<std::string>(res.stacktrace().begin(),
res.stacktrace().end());
return StackTracePeer::LaunchLibunwindSandbox(regs, ns,
uses_custom_forkserver);
}
std::vector<std::string> CompactStackTrace(

View File

@ -19,15 +19,47 @@
#ifndef SANDBOXED_API_SANDBOX2_STACK_TRACE_H_
#define SANDBOXED_API_SANDBOX2_STACK_TRACE_H_
#include <memory>
#include <string>
#include <vector>
#include "absl/status/statusor.h"
#include "sandboxed_api/sandbox2/comms.h"
#include "sandboxed_api/sandbox2/executor.h"
#include "sandboxed_api/sandbox2/namespace.h"
#include "sandboxed_api/sandbox2/policy.h"
#include "sandboxed_api/sandbox2/regs.h"
#include "sandboxed_api/sandbox2/result.h"
namespace sandbox2 {
class Sandbox2;
namespace internal {
class SandboxPeer {
public:
static std::unique_ptr<SandboxPeer> Spawn(std::unique_ptr<Executor> executor,
std::unique_ptr<Policy> policy) {
CHECK_NE(spawn_fn_, nullptr);
return spawn_fn_(std::move(executor), std::move(policy));
}
virtual ~SandboxPeer() = default;
virtual Comms* comms() = 0;
virtual void Kill() = 0;
virtual Result AwaitResult() = 0;
private:
friend class ::sandbox2::Sandbox2;
using SpawnFn = std::unique_ptr<SandboxPeer> (*)(std::unique_ptr<Executor>,
std::unique_ptr<Policy>);
static SpawnFn spawn_fn_;
};
} // namespace internal
// Maximum depth of analyzed call stack.
constexpr size_t kDefaultMaxFrames = 200;