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 // Implementation of the sandbox2::Result class.
16
17 #include "sandboxed_api/sandbox2/result.h"
18
19 #include <sys/resource.h>
20
21 #include <cstdlib>
22 #include <memory>
23 #include <optional>
24 #include <string>
25 #include <vector>
26
27 #include "absl/status/status.h"
28 #include "absl/strings/str_cat.h"
29 #include "absl/strings/str_join.h"
30 #include "sandboxed_api/config.h"
31 #include "sandboxed_api/sandbox2/syscall.h"
32 #include "sandboxed_api/sandbox2/util.h"
33
34 namespace sandbox2 {
35
operator =(const Result & other)36 Result& Result::operator=(const Result& other) {
37 final_status_ = other.final_status_;
38 reason_code_ = other.reason_code_;
39 stack_trace_ = other.stack_trace_;
40 if (other.regs_) {
41 regs_ = std::make_unique<Regs>(*other.regs_);
42 } else {
43 regs_.reset(nullptr);
44 }
45 if (other.syscall_) {
46 syscall_ = std::make_unique<Syscall>(*other.syscall_);
47 } else {
48 syscall_.reset(nullptr);
49 }
50 prog_name_ = other.prog_name_;
51 proc_maps_ = other.proc_maps_;
52 rusage_monitor_ = other.rusage_monitor_;
53 rusage_sandboxee_ = other.rusage_sandboxee_;
54 return *this;
55 }
56
GetStackTrace() const57 std::string Result::GetStackTrace() const {
58 return absl::StrJoin(stack_trace_, " ");
59 }
60
ToStatus() const61 absl::Status Result::ToStatus() const {
62 switch (final_status()) {
63 case OK:
64 if (reason_code() == 0) {
65 return absl::OkStatus();
66 }
67 break;
68 case TIMEOUT:
69 return absl::DeadlineExceededError(ToString());
70 default:
71 break;
72 }
73 return absl::InternalError(ToString());
74 }
75
ToString() const76 std::string Result::ToString() const {
77 std::string result;
78 switch (final_status()) {
79 case sandbox2::Result::UNSET:
80 result = absl::StrCat("UNSET - Code: ", reason_code());
81 break;
82 case sandbox2::Result::OK:
83 result = absl::StrCat("OK - Exit code: ", reason_code());
84 break;
85 case sandbox2::Result::SETUP_ERROR:
86 result = absl::StrCat(
87 "SETUP_ERROR - Code: ",
88 ReasonCodeEnumToString(static_cast<ReasonCodeEnum>(reason_code())));
89 break;
90 case sandbox2::Result::VIOLATION:
91 if (syscall_) {
92 result = absl::StrCat("SYSCALL VIOLATION - Violating Syscall ",
93 syscall_->GetDescription(),
94 " Stack: ", GetStackTrace());
95 } else if (reason_code() == sandbox2::Result::VIOLATION_NETWORK) {
96 result = absl::StrCat("NETWORK VIOLATION: ", GetNetworkViolation());
97 } else {
98 result = "SYSCALL VIOLATION - Unknown Violation";
99 }
100 break;
101 case sandbox2::Result::SIGNALED:
102 result = absl::StrCat("Process terminated with a SIGNAL - Signal: ",
103 util::GetSignalName(reason_code()),
104 " Stack: ", GetStackTrace());
105 break;
106 case sandbox2::Result::TIMEOUT:
107 result = absl::StrCat("Process TIMEOUT - Code: ", reason_code(),
108 " Stack: ", GetStackTrace());
109 break;
110 case sandbox2::Result::EXTERNAL_KILL:
111 result = absl::StrCat("Process killed by user - Code: ", reason_code(),
112 " Stack: ", GetStackTrace());
113 break;
114 case sandbox2::Result::INTERNAL_ERROR:
115 result = absl::StrCat(
116 "INTERNAL_ERROR - Code: ",
117 ReasonCodeEnumToString(static_cast<ReasonCodeEnum>(reason_code())));
118 break;
119 default:
120 result =
121 absl::StrCat("<UNKNOWN>(", final_status(), ") Code: ", reason_code());
122 }
123 if constexpr (sapi::sanitizers::IsAny()) {
124 absl::StrAppend(
125 &result,
126 " - Warning: this executor is built with ASAN, MSAN or TSAN, chances "
127 "are the sandboxee is too, which is incompatible with sandboxing.");
128 } else {
129 if (
130 getenv("COVERAGE") != nullptr) {
131 absl::StrAppend(
132 &result,
133 " - Warning: this executor is built with coverage enabled, chances "
134 "are the sandboxee too, which is incompatible with sandboxing.");
135 }
136 }
137 return result;
138 }
139
StatusEnumToString(StatusEnum value)140 std::string Result::StatusEnumToString(StatusEnum value) {
141 switch (value) {
142 case sandbox2::Result::UNSET:
143 return "UNSET";
144 case sandbox2::Result::OK:
145 return "OK";
146 case sandbox2::Result::SETUP_ERROR:
147 return "SETUP_ERROR";
148 case sandbox2::Result::VIOLATION:
149 return "VIOLATION";
150 case sandbox2::Result::SIGNALED:
151 return "SIGNALED";
152 case sandbox2::Result::TIMEOUT:
153 return "TIMEOUT";
154 case sandbox2::Result::EXTERNAL_KILL:
155 return "EXTERNAL_KILL";
156 case sandbox2::Result::INTERNAL_ERROR:
157 return "INTERNAL_ERROR";
158 }
159 return "UNKNOWN";
160 }
161
ReasonCodeEnumToString(ReasonCodeEnum value)162 std::string Result::ReasonCodeEnumToString(ReasonCodeEnum value) {
163 switch (value) {
164 case sandbox2::Result::UNSUPPORTED_ARCH:
165 return "UNSUPPORTED_ARCH";
166 case sandbox2::Result::FAILED_TIMERS:
167 return "FAILED_TIMERS";
168 case sandbox2::Result::FAILED_SIGNALS:
169 return "FAILED_SIGNALS";
170 case sandbox2::Result::FAILED_SUBPROCESS:
171 return "FAILED_SUBPROCESS";
172 case sandbox2::Result::FAILED_NOTIFY:
173 return "FAILED_NOTIFY";
174 case sandbox2::Result::FAILED_CONNECTION:
175 return "FAILED_CONNECTION";
176 case sandbox2::Result::FAILED_WAIT:
177 return "FAILED_WAIT";
178 case sandbox2::Result::FAILED_NAMESPACES:
179 return "FAILED_NAMESPACES";
180 case sandbox2::Result::FAILED_PTRACE:
181 return "FAILED_PTRACE";
182 case sandbox2::Result::FAILED_IPC:
183 return "FAILED_IPC";
184 case sandbox2::Result::FAILED_LIMITS:
185 return "FAILED_LIMITS";
186 case sandbox2::Result::FAILED_CWD:
187 return "FAILED_CWD";
188 case sandbox2::Result::FAILED_POLICY:
189 return "FAILED_POLICY";
190 case sandbox2::Result::FAILED_STORE:
191 return "FAILED_STORE";
192 case sandbox2::Result::FAILED_FETCH:
193 return "FAILED_FETCH";
194 case sandbox2::Result::FAILED_GETEVENT:
195 return "FAILED_GETEVENT";
196 case sandbox2::Result::FAILED_MONITOR:
197 return "FAILED_MONITOR";
198 case sandbox2::Result::FAILED_KILL:
199 return "FAILED_KILL";
200 case sandbox2::Result::FAILED_INTERRUPT:
201 return "FAILED_INTERRUPT";
202 case sandbox2::Result::FAILED_CHILD:
203 return "FAILED_CHILD";
204 case sandbox2::Result::FAILED_INSPECT:
205 return "FAILED_INSPECT";
206 case sandbox2::Result::VIOLATION_SYSCALL:
207 return "VIOLATION_SYSCALL";
208 case sandbox2::Result::VIOLATION_ARCH:
209 return "VIOLATION_ARCH";
210 case sandbox2::Result::VIOLATION_NETWORK:
211 return "VIOLATION_NETWORK";
212 }
213 return absl::StrCat("UNKNOWN: ", value);
214 }
215
216 } // namespace sandbox2
217