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