xref: /aosp_15_r20/external/sandboxed-api/sandboxed_api/sandbox2/result.h (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
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