1*ec63e07aSXin Li // Copyright 2019 Google LLC 2*ec63e07aSXin Li // 3*ec63e07aSXin Li // Licensed under the Apache License, Version 2.0 (the "License"); 4*ec63e07aSXin Li // you may not use this file except in compliance with the License. 5*ec63e07aSXin Li // You may obtain a copy of the License at 6*ec63e07aSXin Li // 7*ec63e07aSXin Li // https://www.apache.org/licenses/LICENSE-2.0 8*ec63e07aSXin Li // 9*ec63e07aSXin Li // Unless required by applicable law or agreed to in writing, software 10*ec63e07aSXin Li // distributed under the License is distributed on an "AS IS" BASIS, 11*ec63e07aSXin Li // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*ec63e07aSXin Li // See the License for the specific language governing permissions and 13*ec63e07aSXin Li // limitations under the License. 14*ec63e07aSXin Li 15*ec63e07aSXin Li // This file defines the sandbox2::Result class which will in future handle both 16*ec63e07aSXin Li // exit status of the sandboxed process, and possible results returned from it. 17*ec63e07aSXin Li 18*ec63e07aSXin Li #ifndef SANDBOXED_API_SANDBOX2_RESULT_H_ 19*ec63e07aSXin Li #define SANDBOXED_API_SANDBOX2_RESULT_H_ 20*ec63e07aSXin Li 21*ec63e07aSXin Li #include <sys/resource.h> 22*ec63e07aSXin Li 23*ec63e07aSXin Li #include <cstdint> 24*ec63e07aSXin Li #include <memory> 25*ec63e07aSXin Li #include <optional> 26*ec63e07aSXin Li #include <string> 27*ec63e07aSXin Li #include <utility> 28*ec63e07aSXin Li #include <vector> 29*ec63e07aSXin Li 30*ec63e07aSXin Li #include "absl/status/status.h" 31*ec63e07aSXin Li #include "sandboxed_api/config.h" 32*ec63e07aSXin Li #include "sandboxed_api/sandbox2/regs.h" 33*ec63e07aSXin Li #include "sandboxed_api/sandbox2/syscall.h" 34*ec63e07aSXin Li 35*ec63e07aSXin Li namespace sandbox2 { 36*ec63e07aSXin Li 37*ec63e07aSXin Li class Result { 38*ec63e07aSXin Li public: 39*ec63e07aSXin Li // Final execution status. 40*ec63e07aSXin Li enum StatusEnum { 41*ec63e07aSXin Li // Not set yet 42*ec63e07aSXin Li UNSET = 0, 43*ec63e07aSXin Li // OK 44*ec63e07aSXin Li OK, 45*ec63e07aSXin Li // Sandbox initialization failure 46*ec63e07aSXin Li SETUP_ERROR, 47*ec63e07aSXin Li // Syscall violation 48*ec63e07aSXin Li VIOLATION, 49*ec63e07aSXin Li // Process terminated with a signal 50*ec63e07aSXin Li SIGNALED, 51*ec63e07aSXin Li // Process terminated with a timeout 52*ec63e07aSXin Li TIMEOUT, 53*ec63e07aSXin Li // Killed externally by user 54*ec63e07aSXin Li EXTERNAL_KILL, 55*ec63e07aSXin Li // Most likely ptrace() API failed 56*ec63e07aSXin Li INTERNAL_ERROR, 57*ec63e07aSXin Li }; 58*ec63e07aSXin Li 59*ec63e07aSXin Li // Detailed reason codes 60*ec63e07aSXin Li enum ReasonCodeEnum { 61*ec63e07aSXin Li // Codes used by status=`SETUP_ERROR`: 62*ec63e07aSXin Li UNSUPPORTED_ARCH = 0, 63*ec63e07aSXin Li FAILED_TIMERS, 64*ec63e07aSXin Li FAILED_SIGNALS, 65*ec63e07aSXin Li FAILED_SUBPROCESS, 66*ec63e07aSXin Li FAILED_NOTIFY, 67*ec63e07aSXin Li FAILED_CONNECTION, 68*ec63e07aSXin Li FAILED_WAIT, 69*ec63e07aSXin Li FAILED_NAMESPACES, 70*ec63e07aSXin Li FAILED_PTRACE, 71*ec63e07aSXin Li FAILED_IPC, 72*ec63e07aSXin Li FAILED_LIMITS, 73*ec63e07aSXin Li FAILED_CWD, 74*ec63e07aSXin Li FAILED_POLICY, 75*ec63e07aSXin Li 76*ec63e07aSXin Li // Codes used by status=`INTERNAL_ERROR`: 77*ec63e07aSXin Li FAILED_STORE, 78*ec63e07aSXin Li FAILED_FETCH, 79*ec63e07aSXin Li FAILED_GETEVENT, 80*ec63e07aSXin Li FAILED_MONITOR, 81*ec63e07aSXin Li FAILED_KILL, 82*ec63e07aSXin Li FAILED_INTERRUPT, 83*ec63e07aSXin Li FAILED_CHILD, 84*ec63e07aSXin Li FAILED_INSPECT, 85*ec63e07aSXin Li 86*ec63e07aSXin Li // TODO(wiktorg) not used currently (syscall number stored insted) - need to 87*ec63e07aSXin Li // fix clients first 88*ec63e07aSXin Li // Codes used by status=`VIOLATION`: 89*ec63e07aSXin Li VIOLATION_SYSCALL, 90*ec63e07aSXin Li VIOLATION_ARCH, 91*ec63e07aSXin Li VIOLATION_NETWORK = 0x10000000, // TODO(eternalred): temporary value, needs 92*ec63e07aSXin Li // to be big until it's fixed 93*ec63e07aSXin Li }; 94*ec63e07aSXin Li 95*ec63e07aSXin Li Result() = default; Result(const Result & other)96*ec63e07aSXin Li Result(const Result& other) { *this = other; } 97*ec63e07aSXin Li Result& operator=(const Result& other); 98*ec63e07aSXin Li Result(Result&&) = default; 99*ec63e07aSXin Li Result& operator=(Result&&) = default; 100*ec63e07aSXin Li IgnoreResult()101*ec63e07aSXin Li void IgnoreResult() const {} 102*ec63e07aSXin Li 103*ec63e07aSXin Li // Setters/getters for the final status/code value. SetExitStatusCode(StatusEnum final_status,uintptr_t reason_code)104*ec63e07aSXin Li void SetExitStatusCode(StatusEnum final_status, uintptr_t reason_code) { 105*ec63e07aSXin Li // Don't overwrite exit status codes. 106*ec63e07aSXin Li if (final_status_ != UNSET) { 107*ec63e07aSXin Li return; 108*ec63e07aSXin Li } 109*ec63e07aSXin Li final_status_ = final_status; 110*ec63e07aSXin Li reason_code_ = reason_code; 111*ec63e07aSXin Li } 112*ec63e07aSXin Li 113*ec63e07aSXin Li // Sets the stack trace. 114*ec63e07aSXin Li // The stacktrace must be sometimes fetched before SetExitStatusCode is 115*ec63e07aSXin Li // called, because after WIFEXITED() or WIFSIGNALED() the process is just a 116*ec63e07aSXin Li // zombie. set_stack_trace(std::vector<std::string> value)117*ec63e07aSXin Li void set_stack_trace(std::vector<std::string> value) { 118*ec63e07aSXin Li stack_trace_ = std::move(value); 119*ec63e07aSXin Li } 120*ec63e07aSXin Li SetRegs(std::unique_ptr<Regs> regs)121*ec63e07aSXin Li void SetRegs(std::unique_ptr<Regs> regs) { regs_ = std::move(regs); } 122*ec63e07aSXin Li SetSyscall(std::unique_ptr<Syscall> syscall)123*ec63e07aSXin Li void SetSyscall(std::unique_ptr<Syscall> syscall) { 124*ec63e07aSXin Li syscall_ = std::move(syscall); 125*ec63e07aSXin Li } 126*ec63e07aSXin Li SetNetworkViolation(std::string network_violation)127*ec63e07aSXin Li void SetNetworkViolation(std::string network_violation) { 128*ec63e07aSXin Li network_violation_ = std::move(network_violation); 129*ec63e07aSXin Li } 130*ec63e07aSXin Li final_status()131*ec63e07aSXin Li StatusEnum final_status() const { return final_status_; } reason_code()132*ec63e07aSXin Li uintptr_t reason_code() const { return reason_code_; } 133*ec63e07aSXin Li 134*ec63e07aSXin Li // If true, indicates that the non-OK status is transient and a retry might 135*ec63e07aSXin Li // succeed. IsRetryable()136*ec63e07aSXin Li bool IsRetryable() const { return false; } 137*ec63e07aSXin Li 138*ec63e07aSXin Li // Returns the current syscall architecture. 139*ec63e07aSXin Li // Client architecture when final_status_ == VIOLATION, might be different 140*ec63e07aSXin Li // from the host architecture (32-bit vs 64-bit syscalls). GetSyscallArch()141*ec63e07aSXin Li sapi::cpu::Architecture GetSyscallArch() const { 142*ec63e07aSXin Li return syscall_ ? syscall_->arch() : sapi::cpu::kUnknown; 143*ec63e07aSXin Li } 144*ec63e07aSXin Li stack_trace()145*ec63e07aSXin Li const std::vector<std::string>& stack_trace() const { return stack_trace_; } 146*ec63e07aSXin Li 147*ec63e07aSXin Li // Returns the stack trace as a space-delimited string. 148*ec63e07aSXin Li std::string GetStackTrace() const; 149*ec63e07aSXin Li GetRegs()150*ec63e07aSXin Li const Regs* GetRegs() const { return regs_.get(); } 151*ec63e07aSXin Li GetSyscall()152*ec63e07aSXin Li const Syscall* GetSyscall() const { return syscall_.get(); } 153*ec63e07aSXin Li GetProgName()154*ec63e07aSXin Li const std::string& GetProgName() const { return prog_name_; } 155*ec63e07aSXin Li GetNetworkViolation()156*ec63e07aSXin Li const std::string& GetNetworkViolation() const { return network_violation_; } 157*ec63e07aSXin Li SetProgName(const std::string & name)158*ec63e07aSXin Li void SetProgName(const std::string& name) { prog_name_ = name; } 159*ec63e07aSXin Li GetProcMaps()160*ec63e07aSXin Li const std::string& GetProcMaps() const { return proc_maps_; } 161*ec63e07aSXin Li SetProcMaps(const std::string & proc_maps)162*ec63e07aSXin Li void SetProcMaps(const std::string& proc_maps) { proc_maps_ = proc_maps; } 163*ec63e07aSXin Li 164*ec63e07aSXin Li // Converts this result to a absl::Status object. The status will only be 165*ec63e07aSXin Li // OK if the sandbox process exited normally with an exit code of 0. 166*ec63e07aSXin Li absl::Status ToStatus() const; 167*ec63e07aSXin Li 168*ec63e07aSXin Li // Returns a descriptive string for final result. 169*ec63e07aSXin Li std::string ToString() const; 170*ec63e07aSXin Li 171*ec63e07aSXin Li // Converts StatusEnum to a string. 172*ec63e07aSXin Li static std::string StatusEnumToString(StatusEnum value); 173*ec63e07aSXin Li 174*ec63e07aSXin Li // Converts ReasonCodeEnum to a string. 175*ec63e07aSXin Li static std::string ReasonCodeEnumToString(ReasonCodeEnum value); 176*ec63e07aSXin Li GetRUsageMonitor()177*ec63e07aSXin Li rusage* GetRUsageMonitor() { return &rusage_monitor_; } 178*ec63e07aSXin Li 179*ec63e07aSXin Li // Only set by the unotify monitor. GetRUsageSandboxee()180*ec63e07aSXin Li const std::optional<rusage>& GetRUsageSandboxee() const { 181*ec63e07aSXin Li return rusage_sandboxee_; 182*ec63e07aSXin Li } 183*ec63e07aSXin Li SetRUsageSandboxee(rusage usage)184*ec63e07aSXin Li void SetRUsageSandboxee(rusage usage) { rusage_sandboxee_ = usage; } 185*ec63e07aSXin Li 186*ec63e07aSXin Li private: 187*ec63e07aSXin Li // Final execution status - see 'StatusEnum' for details. 188*ec63e07aSXin Li StatusEnum final_status_ = UNSET; 189*ec63e07aSXin Li // Termination cause: 190*ec63e07aSXin Li // a). process exit value if final_status_ == OK, 191*ec63e07aSXin Li // b). terminating signal if final_status_ == SIGNALED, 192*ec63e07aSXin Li // c). violating syscall if final_status_ == VIOLATION, 193*ec63e07aSXin Li // unspecified for the rest of status_ values. 194*ec63e07aSXin Li uintptr_t reason_code_ = 0; 195*ec63e07aSXin Li // Might contain stack-trace of the process, especially if it failed with 196*ec63e07aSXin Li // syscall violation, or was terminated by a signal. 197*ec63e07aSXin Li std::vector<std::string> stack_trace_; 198*ec63e07aSXin Li // Might contain the register values of the process, similar to the stack. 199*ec63e07aSXin Li // trace 200*ec63e07aSXin Li std::unique_ptr<Regs> regs_; 201*ec63e07aSXin Li // Might contain violating syscall information 202*ec63e07aSXin Li std::unique_ptr<Syscall> syscall_; 203*ec63e07aSXin Li // Name of the process (as it can not be accessed anymore after termination). 204*ec63e07aSXin Li std::string prog_name_; 205*ec63e07aSXin Li // /proc/pid/maps of the main process. 206*ec63e07aSXin Li std::string proc_maps_; 207*ec63e07aSXin Li // IP and port if network violation occurred 208*ec63e07aSXin Li std::string network_violation_; 209*ec63e07aSXin Li // Final resource usage as defined in <sys/resource.h> (man getrusage), for 210*ec63e07aSXin Li // the Monitor thread. 211*ec63e07aSXin Li rusage rusage_monitor_; 212*ec63e07aSXin Li // Final resource usage for the sandboxee process, only for unotify monitor. 213*ec63e07aSXin Li std::optional<rusage> rusage_sandboxee_; 214*ec63e07aSXin Li }; 215*ec63e07aSXin Li 216*ec63e07aSXin Li } // namespace sandbox2 217*ec63e07aSXin Li 218*ec63e07aSXin Li #endif // SANDBOXED_API_SANDBOX2_RESULT_H_ 219