| // Copyright 2019 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| // Implementation of the sandbox2::Result class. |
| |
| #include "sandboxed_api/sandbox2/result.h" |
| |
| #include <sys/resource.h> |
| |
| #include <cstdlib> |
| #include <memory> |
| #include <optional> |
| #include <string> |
| #include <vector> |
| |
| #include "absl/status/status.h" |
| #include "absl/strings/str_cat.h" |
| #include "absl/strings/str_join.h" |
| #include "sandboxed_api/config.h" |
| #include "sandboxed_api/sandbox2/syscall.h" |
| #include "sandboxed_api/sandbox2/util.h" |
| |
| namespace sandbox2 { |
| |
| Result& Result::operator=(const Result& other) { |
| final_status_ = other.final_status_; |
| reason_code_ = other.reason_code_; |
| stack_trace_ = other.stack_trace_; |
| if (other.regs_) { |
| regs_ = std::make_unique<Regs>(*other.regs_); |
| } else { |
| regs_.reset(nullptr); |
| } |
| if (other.syscall_) { |
| syscall_ = std::make_unique<Syscall>(*other.syscall_); |
| } else { |
| syscall_.reset(nullptr); |
| } |
| prog_name_ = other.prog_name_; |
| proc_maps_ = other.proc_maps_; |
| rusage_monitor_ = other.rusage_monitor_; |
| rusage_sandboxee_ = other.rusage_sandboxee_; |
| return *this; |
| } |
| |
| std::string Result::GetStackTrace() const { |
| return absl::StrJoin(stack_trace_, " "); |
| } |
| |
| absl::Status Result::ToStatus() const { |
| switch (final_status()) { |
| case OK: |
| if (reason_code() == 0) { |
| return absl::OkStatus(); |
| } |
| break; |
| case TIMEOUT: |
| return absl::DeadlineExceededError(ToString()); |
| default: |
| break; |
| } |
| return absl::InternalError(ToString()); |
| } |
| |
| std::string Result::ToString() const { |
| std::string result; |
| switch (final_status()) { |
| case sandbox2::Result::UNSET: |
| result = absl::StrCat("UNSET - Code: ", reason_code()); |
| break; |
| case sandbox2::Result::OK: |
| result = absl::StrCat("OK - Exit code: ", reason_code()); |
| break; |
| case sandbox2::Result::SETUP_ERROR: |
| result = absl::StrCat( |
| "SETUP_ERROR - Code: ", |
| ReasonCodeEnumToString(static_cast<ReasonCodeEnum>(reason_code()))); |
| break; |
| case sandbox2::Result::VIOLATION: |
| if (syscall_) { |
| result = absl::StrCat("SYSCALL VIOLATION - Violating Syscall ", |
| syscall_->GetDescription(), |
| " Stack: ", GetStackTrace()); |
| } else if (reason_code() == sandbox2::Result::VIOLATION_NETWORK) { |
| result = absl::StrCat("NETWORK VIOLATION: ", GetNetworkViolation()); |
| } else { |
| result = "SYSCALL VIOLATION - Unknown Violation"; |
| } |
| break; |
| case sandbox2::Result::SIGNALED: |
| result = absl::StrCat("Process terminated with a SIGNAL - Signal: ", |
| util::GetSignalName(reason_code()), |
| " Stack: ", GetStackTrace()); |
| break; |
| case sandbox2::Result::TIMEOUT: |
| result = absl::StrCat("Process TIMEOUT - Code: ", reason_code(), |
| " Stack: ", GetStackTrace()); |
| break; |
| case sandbox2::Result::EXTERNAL_KILL: |
| result = absl::StrCat("Process killed by user - Code: ", reason_code(), |
| " Stack: ", GetStackTrace()); |
| break; |
| case sandbox2::Result::INTERNAL_ERROR: |
| result = absl::StrCat( |
| "INTERNAL_ERROR - Code: ", |
| ReasonCodeEnumToString(static_cast<ReasonCodeEnum>(reason_code()))); |
| break; |
| default: |
| result = |
| absl::StrCat("<UNKNOWN>(", final_status(), ") Code: ", reason_code()); |
| } |
| if constexpr (sapi::sanitizers::IsAny()) { |
| absl::StrAppend( |
| &result, |
| " - Warning: this executor is built with ASAN, MSAN or TSAN, chances " |
| "are the sandboxee is too, which is incompatible with sandboxing."); |
| } else { |
| if ( |
| getenv("COVERAGE") != nullptr) { |
| absl::StrAppend( |
| &result, |
| " - Warning: this executor is built with coverage enabled, chances " |
| "are the sandboxee too, which is incompatible with sandboxing."); |
| } |
| } |
| return result; |
| } |
| |
| std::string Result::StatusEnumToString(StatusEnum value) { |
| switch (value) { |
| case sandbox2::Result::UNSET: |
| return "UNSET"; |
| case sandbox2::Result::OK: |
| return "OK"; |
| case sandbox2::Result::SETUP_ERROR: |
| return "SETUP_ERROR"; |
| case sandbox2::Result::VIOLATION: |
| return "VIOLATION"; |
| case sandbox2::Result::SIGNALED: |
| return "SIGNALED"; |
| case sandbox2::Result::TIMEOUT: |
| return "TIMEOUT"; |
| case sandbox2::Result::EXTERNAL_KILL: |
| return "EXTERNAL_KILL"; |
| case sandbox2::Result::INTERNAL_ERROR: |
| return "INTERNAL_ERROR"; |
| } |
| return "UNKNOWN"; |
| } |
| |
| std::string Result::ReasonCodeEnumToString(ReasonCodeEnum value) { |
| switch (value) { |
| case sandbox2::Result::UNSUPPORTED_ARCH: |
| return "UNSUPPORTED_ARCH"; |
| case sandbox2::Result::FAILED_TIMERS: |
| return "FAILED_TIMERS"; |
| case sandbox2::Result::FAILED_SIGNALS: |
| return "FAILED_SIGNALS"; |
| case sandbox2::Result::FAILED_SUBPROCESS: |
| return "FAILED_SUBPROCESS"; |
| case sandbox2::Result::FAILED_NOTIFY: |
| return "FAILED_NOTIFY"; |
| case sandbox2::Result::FAILED_CONNECTION: |
| return "FAILED_CONNECTION"; |
| case sandbox2::Result::FAILED_WAIT: |
| return "FAILED_WAIT"; |
| case sandbox2::Result::FAILED_NAMESPACES: |
| return "FAILED_NAMESPACES"; |
| case sandbox2::Result::FAILED_PTRACE: |
| return "FAILED_PTRACE"; |
| case sandbox2::Result::FAILED_IPC: |
| return "FAILED_IPC"; |
| case sandbox2::Result::FAILED_LIMITS: |
| return "FAILED_LIMITS"; |
| case sandbox2::Result::FAILED_CWD: |
| return "FAILED_CWD"; |
| case sandbox2::Result::FAILED_POLICY: |
| return "FAILED_POLICY"; |
| case sandbox2::Result::FAILED_STORE: |
| return "FAILED_STORE"; |
| case sandbox2::Result::FAILED_FETCH: |
| return "FAILED_FETCH"; |
| case sandbox2::Result::FAILED_GETEVENT: |
| return "FAILED_GETEVENT"; |
| case sandbox2::Result::FAILED_MONITOR: |
| return "FAILED_MONITOR"; |
| case sandbox2::Result::FAILED_KILL: |
| return "FAILED_KILL"; |
| case sandbox2::Result::FAILED_INTERRUPT: |
| return "FAILED_INTERRUPT"; |
| case sandbox2::Result::FAILED_CHILD: |
| return "FAILED_CHILD"; |
| case sandbox2::Result::FAILED_INSPECT: |
| return "FAILED_INSPECT"; |
| case sandbox2::Result::VIOLATION_SYSCALL: |
| return "VIOLATION_SYSCALL"; |
| case sandbox2::Result::VIOLATION_ARCH: |
| return "VIOLATION_ARCH"; |
| case sandbox2::Result::VIOLATION_NETWORK: |
| return "VIOLATION_NETWORK"; |
| } |
| return absl::StrCat("UNKNOWN: ", value); |
| } |
| |
| } // namespace sandbox2 |