diff --git a/sandboxed_api/sandbox2/BUILD.bazel b/sandboxed_api/sandbox2/BUILD.bazel index 3ccf2df..f1f4c2a 100644 --- a/sandboxed_api/sandbox2/BUILD.bazel +++ b/sandboxed_api/sandbox2/BUILD.bazel @@ -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", diff --git a/sandboxed_api/sandbox2/CMakeLists.txt b/sandboxed_api/sandbox2/CMakeLists.txt index dad2003..e7ab9e4 100644 --- a/sandboxed_api/sandbox2/CMakeLists.txt +++ b/sandboxed_api/sandbox2/CMakeLists.txt @@ -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 diff --git a/sandboxed_api/sandbox2/monitor_base.cc b/sandboxed_api/sandbox2/monitor_base.cc index 75fec9a..6e06ea9 100644 --- a/sandboxed_api/sandbox2/monitor_base.cc +++ b/sandboxed_api/sandbox2/monitor_base.cc @@ -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> MonitorBase::GetStackTrace( + const Regs* regs) { + return sandbox2::GetStackTrace(regs, policy_->GetNamespace(), + uses_custom_forkserver_); +} + +absl::StatusOr> 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 diff --git a/sandboxed_api/sandbox2/monitor_base.h b/sandboxed_api/sandbox2/monitor_base.h index e7a5c12..ac0587e 100644 --- a/sandboxed_api/sandbox2/monitor_base.h +++ b/sandboxed_api/sandbox2/monitor_base.h @@ -24,6 +24,8 @@ #include #include #include +#include +#include #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> GetStackTrace(const Regs* regs); + + // Gets and logs stack trace. + absl::StatusOr> 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 diff --git a/sandboxed_api/sandbox2/monitor_ptrace.cc b/sandboxed_api/sandbox2/monitor_ptrace.cc index 0e962a0..00b4430 100644 --- a/sandboxed_api/sandbox2/monitor_ptrace.cc +++ b/sandboxed_api/sandbox2/monitor_ptrace.cc @@ -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> PtraceMonitor::GetAndLogStackTrace( - const Regs* regs) { - SAPI_ASSIGN_OR_RETURN( - std::vector 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) { 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> { Regs regs(pid); SAPI_RETURN_IF_ERROR(regs.Fetch()); - return GetStackTrace(®s, policy_->GetNamespace(), - uses_custom_forkserver_); + return GetStackTrace(®s); }(); if (!stack_trace.ok()) { diff --git a/sandboxed_api/sandbox2/monitor_ptrace.h b/sandboxed_api/sandbox2/monitor_ptrace.h index 8bcac20..b11a6e3 100644 --- a/sandboxed_api/sandbox2/monitor_ptrace.h +++ b/sandboxed_api/sandbox2/monitor_ptrace.h @@ -25,7 +25,6 @@ #include #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); @@ -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> 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 syscalls_in_progress_; sigset_t sset_; - // Is the sandboxee forked from a custom forkserver? - bool uses_custom_forkserver_; // Monitor thread object. std::unique_ptr thread_; diff --git a/sandboxed_api/sandbox2/sandbox2.cc b/sandboxed_api/sandbox2/sandbox2.cc index 469bac3..6ae0964 100644 --- a/sandboxed_api/sandbox2/sandbox2.cc +++ b/sandboxed_api/sandbox2/sandbox2.cc @@ -19,15 +19,45 @@ #include #include #include +#include +#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 Spawn(std::unique_ptr executor, + std::unique_ptr policy) { + return std::make_unique(std::move(executor), + std::move(policy)); + } + + Sandbox2Peer(std::unique_ptr executor, + std::unique_ptr 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 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(executor_.get(), policy_.get(), notify_.get()); monitor_->Launch(); diff --git a/sandboxed_api/sandbox2/stack_trace.cc b/sandboxed_api/sandbox2/stack_trace.cc index 8cbc702..119712b 100644 --- a/sandboxed_api/sandbox2/stack_trace.cc +++ b/sandboxed_api/sandbox2/stack_trace.cc @@ -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 LaunchLibunwindSandbox( + static absl::StatusOr> LaunchLibunwindSandbox( const Regs* regs, const Namespace* ns, bool uses_custom_forkserver); }; @@ -163,7 +158,11 @@ absl::StatusOr> StackTracePeer::GetPolicy( return std::move(policy); } -absl::StatusOr StackTracePeer::LaunchLibunwindSandbox( +namespace internal { +SandboxPeer::SpawnFn SandboxPeer::spawn_fn_ = nullptr; +} // namespace internal + +absl::StatusOr> StackTracePeer::LaunchLibunwindSandbox( const Regs* regs, const Namespace* ns, bool uses_custom_forkserver) { const pid_t pid = regs->pid(); @@ -240,11 +239,11 @@ absl::StatusOr StackTracePeer::LaunchLibunwindSandbox( std::unique_ptr 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 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 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 StackTracePeer::LaunchLibunwindSandbox( sandbox_result.ToString())); } - return result; + return std::vector(result.stacktrace().begin(), + result.stacktrace().end()); } absl::StatusOr> GetStackTrace( @@ -317,11 +317,8 @@ absl::StatusOr> GetStackTrace( return UnsafeGetStackTrace(regs->pid()); } - SAPI_ASSIGN_OR_RETURN( - UnwindResult res, - StackTracePeer::LaunchLibunwindSandbox(regs, ns, uses_custom_forkserver)); - return std::vector(res.stacktrace().begin(), - res.stacktrace().end()); + return StackTracePeer::LaunchLibunwindSandbox(regs, ns, + uses_custom_forkserver); } std::vector CompactStackTrace( diff --git a/sandboxed_api/sandbox2/stack_trace.h b/sandboxed_api/sandbox2/stack_trace.h index 1d10c7b..f3932bb 100644 --- a/sandboxed_api/sandbox2/stack_trace.h +++ b/sandboxed_api/sandbox2/stack_trace.h @@ -19,15 +19,47 @@ #ifndef SANDBOXED_API_SANDBOX2_STACK_TRACE_H_ #define SANDBOXED_API_SANDBOX2_STACK_TRACE_H_ +#include #include #include #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 Spawn(std::unique_ptr executor, + std::unique_ptr 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 (*)(std::unique_ptr, + std::unique_ptr); + static SpawnFn spawn_fn_; +}; + +} // namespace internal + // Maximum depth of analyzed call stack. constexpr size_t kDefaultMaxFrames = 200;