sandboxed-api/sandboxed_api/sandbox2/result.h
Christian Blichmann dbaf95c724 Move utility code into sandboxed_api/util
This change should make it less confusing where utility code comes from.
Having it in two places made sense when we were debating whether to publish
Sandbox2 separately, but not any longer.

Follow-up changes will move `sandbox2/util.h` and rename the remaining
`sandbox2/util` folder.

PiperOrigin-RevId: 351601640
Change-Id: I6256845261f610e590c25e2c59851cc51da2d778
2021-01-13 09:25:52 -08:00

204 lines
6.2 KiB
C++

// 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
//
// http://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.
// This file defines the sandbox2::Result class which will in future handle both
// exit status of the sandboxed process, and possible results returned from it.
#ifndef SANDBOXED_API_SANDBOX2_RESULT_H_
#define SANDBOXED_API_SANDBOX2_RESULT_H_
#include <sys/resource.h>
#include <sys/types.h>
#include <cstdint>
#include <memory>
#include <string>
#include <utility>
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "sandboxed_api/config.h"
#include "sandboxed_api/sandbox2/regs.h"
#include "sandboxed_api/sandbox2/syscall.h"
namespace sandbox2 {
class Result {
public:
// Final execution status.
enum StatusEnum {
// Not set yet
UNSET = 0,
// OK
OK,
// Sandbox initialization failure
SETUP_ERROR,
// Syscall violation
VIOLATION,
// Process terminated with a signal
SIGNALED,
// Process terminated with a timeout
TIMEOUT,
// Killed externally by user
EXTERNAL_KILL,
// Most likely ptrace() API failed
INTERNAL_ERROR,
};
// Detailed reason codes
enum ReasonCodeEnum {
// Codes used by status=`SETUP_ERROR`:
UNSUPPORTED_ARCH = 0,
FAILED_TIMERS,
FAILED_SIGNALS,
FAILED_SUBPROCESS,
FAILED_NOTIFY,
FAILED_CONNECTION,
FAILED_WAIT,
FAILED_NAMESPACES,
FAILED_PTRACE,
FAILED_IPC,
FAILED_LIMITS,
FAILED_CWD,
FAILED_POLICY,
// Codes used by status=`INTERNAL_ERROR`:
FAILED_STORE,
FAILED_FETCH,
FAILED_GETEVENT,
FAILED_MONITOR,
FAILED_KILL,
FAILED_CHILD,
// TODO(wiktorg) not used currently (syscall number stored insted) - need to
// fix clients first
// Codes used by status=`VIOLATION`:
VIOLATION_SYSCALL,
VIOLATION_ARCH,
VIOLATION_NETWORK = 0x10000000, // TODO(eternalred): temporary value, needs
// to be big until it's fixed
};
Result() = default;
Result(const Result& other) { *this = other; }
Result& operator=(const Result& other);
Result(Result&&) = default;
Result& operator=(Result&&) = default;
void IgnoreResult() const {}
// Setters/getters for the final status/code value.
void SetExitStatusCode(StatusEnum final_status, uintptr_t reason_code) {
// Don't overwrite exit status codes.
if (final_status_ != UNSET) {
return;
}
final_status_ = final_status;
reason_code_ = reason_code;
}
// Sets the stack trace.
// The stacktrace must be sometimes fetched before SetExitStatusCode is
// called, because after WIFEXITED() or WIFSIGNALED() the process is just a
// zombie.
void set_stack_trace(std::vector<std::string> value) {
stack_trace_ = std::move(value);
}
void SetRegs(std::unique_ptr<Regs> regs) { regs_ = std::move(regs); }
void SetSyscall(std::unique_ptr<Syscall> syscall) {
syscall_ = std::move(syscall);
}
void SetNetworkViolation(std::string network_violation) {
network_violation_ = std::move(network_violation);
}
StatusEnum final_status() const { return final_status_; }
uintptr_t reason_code() const { return reason_code_; }
// Returns the current syscall architecture.
// Client architecture when final_status_ == VIOLATION, might be different
// from the host architecture (32-bit vs 64-bit syscalls).
sapi::cpu::Architecture GetSyscallArch() const {
return syscall_ ? syscall_->arch() : sapi::cpu::kUnknown;
}
const std::vector<std::string> stack_trace() { return stack_trace_; }
// Returns the stack trace as a space-delimited string.
std::string GetStackTrace() const;
const Regs* GetRegs() const { return regs_.get(); }
const Syscall* GetSyscall() const { return syscall_.get(); }
const std::string& GetProgName() const { return prog_name_; }
const std::string& GetNetworkViolation() const { return network_violation_; }
void SetProgName(const std::string& name) { prog_name_ = name; }
const std::string& GetProcMaps() const { return proc_maps_; }
void SetProcMaps(const std::string& proc_maps) { proc_maps_ = proc_maps; }
// Converts this result to a absl::Status object. The status will only be
// OK if the sandbox process exited normally with an exit code of 0.
absl::Status ToStatus() const;
// Returns a descriptive string for final result.
std::string ToString() const;
// Converts StatusEnum to a string.
static std::string StatusEnumToString(StatusEnum value);
// Converts ReasonCodeEnum to a string.
static std::string ReasonCodeEnumToString(ReasonCodeEnum value);
rusage* GetRUsageMonitor() { return &rusage_monitor_; }
private:
// Final execution status - see 'StatusEnum' for details.
StatusEnum final_status_ = UNSET;
// Termination cause:
// a). process exit value if final_status_ == OK,
// b). terminating signal if final_status_ == SIGNALED,
// c). violating syscall if final_status_ == VIOLATION,
// unspecified for the rest of status_ values.
uintptr_t reason_code_ = 0;
// Might contain stack-trace of the process, especially if it failed with
// syscall violation, or was terminated by a signal.
std::vector<std::string> stack_trace_;
// Might contain the register values of the process, similar to the stack.
// trace
std::unique_ptr<Regs> regs_;
// Might contain violating syscall information
std::unique_ptr<Syscall> syscall_;
// Name of the process (as it can not be accessed anymore after termination).
std::string prog_name_;
// /proc/pid/maps of the main process.
std::string proc_maps_;
// IP and port if network violation occurred
std::string network_violation_;
// Final resource usage as defined in <sys/resource.h> (man getrusage), for
// the Monitor thread.
rusage rusage_monitor_;
};
} // namespace sandbox2
#endif // SANDBOXED_API_SANDBOX2_RESULT_H_