mirror of
https://github.com/google/sandboxed-api.git
synced 2024-03-22 13:11:30 +08:00
Internal change.
PiperOrigin-RevId: 265057217 Change-Id: Id00c867b373dbe8c9112c23ef4b0300ed3ca9e5b
This commit is contained in:
parent
d91879f752
commit
276b7efc92
|
@ -23,62 +23,62 @@
|
|||
|
||||
namespace sapi {
|
||||
|
||||
::sapi::Status RPCChannel::Call(const FuncCall& call, uint32_t tag,
|
||||
FuncRet* ret, v::Type exp_type) {
|
||||
sapi::Status RPCChannel::Call(const FuncCall& call, uint32_t tag, FuncRet* ret,
|
||||
v::Type exp_type) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
if (!comms_->SendTLV(tag, sizeof(call),
|
||||
reinterpret_cast<const uint8_t*>(&call))) {
|
||||
return ::sapi::UnavailableError("Sending TLV value failed");
|
||||
return sapi::UnavailableError("Sending TLV value failed");
|
||||
}
|
||||
SAPI_ASSIGN_OR_RETURN(auto fret, Return(exp_type));
|
||||
*ret = fret;
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
::sapi::StatusOr<FuncRet> RPCChannel::Return(v::Type exp_type) {
|
||||
sapi::StatusOr<FuncRet> RPCChannel::Return(v::Type exp_type) {
|
||||
uint32_t tag;
|
||||
uint64_t len;
|
||||
FuncRet ret;
|
||||
if (!comms_->RecvTLV(&tag, &len, &ret, sizeof(ret))) {
|
||||
return ::sapi::UnavailableError("Receiving TLV value failed");
|
||||
return sapi::UnavailableError("Receiving TLV value failed");
|
||||
}
|
||||
if (tag != comms::kMsgReturn) {
|
||||
LOG(ERROR) << "tag != comms::kMsgReturn (" << absl::StrCat(absl::Hex(tag))
|
||||
<< " != " << absl::StrCat(absl::Hex(comms::kMsgReturn)) << ")";
|
||||
return ::sapi::UnavailableError("Received TLV has incorrect tag");
|
||||
return sapi::UnavailableError("Received TLV has incorrect tag");
|
||||
}
|
||||
if (len != sizeof(FuncRet)) {
|
||||
LOG(ERROR) << "len != sizeof(FuncReturn) (" << len
|
||||
<< " != " << sizeof(FuncRet) << ")";
|
||||
return ::sapi::UnavailableError("Received TLV has incorrect length");
|
||||
return sapi::UnavailableError("Received TLV has incorrect length");
|
||||
}
|
||||
if (ret.ret_type != exp_type) {
|
||||
LOG(ERROR) << "FuncRet->type != exp_type (" << ret.ret_type
|
||||
<< " != " << exp_type << ")";
|
||||
return ::sapi::UnavailableError("Received TLV has incorrect return type");
|
||||
return sapi::UnavailableError("Received TLV has incorrect return type");
|
||||
}
|
||||
if (!ret.success) {
|
||||
LOG(ERROR) << "FuncRet->success == false";
|
||||
return ::sapi::UnavailableError("Function call failed");
|
||||
return sapi::UnavailableError("Function call failed");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
::sapi::Status RPCChannel::Allocate(size_t size, void** addr) {
|
||||
sapi::Status RPCChannel::Allocate(size_t size, void** addr) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
uint64_t sz = size;
|
||||
if (!comms_->SendTLV(comms::kMsgAllocate, sizeof(sz),
|
||||
reinterpret_cast<uint8_t*>(&sz))) {
|
||||
return ::sapi::UnavailableError("Sending TLV value failed");
|
||||
return sapi::UnavailableError("Sending TLV value failed");
|
||||
}
|
||||
|
||||
SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kPointer));
|
||||
*addr = reinterpret_cast<void*>(fret.int_val);
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
::sapi::Status RPCChannel::Reallocate(void* old_addr, size_t size,
|
||||
void** new_addr) {
|
||||
sapi::Status RPCChannel::Reallocate(void* old_addr, size_t size,
|
||||
void** new_addr) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
comms::ReallocRequest req;
|
||||
req.old_addr = reinterpret_cast<uint64_t>(old_addr);
|
||||
|
@ -86,54 +86,54 @@ namespace sapi {
|
|||
|
||||
if (!comms_->SendTLV(comms::kMsgReallocate, sizeof(comms::ReallocRequest),
|
||||
reinterpret_cast<uint8_t*>(&req))) {
|
||||
return ::sapi::UnavailableError("Sending TLV value failed");
|
||||
return sapi::UnavailableError("Sending TLV value failed");
|
||||
}
|
||||
|
||||
auto fret_or = Return(v::Type::kPointer);
|
||||
if (!fret_or.ok()) {
|
||||
*new_addr = nullptr;
|
||||
return ::sapi::UnavailableError(
|
||||
return sapi::UnavailableError(
|
||||
absl::StrCat("Reallocate() failed on the remote side: ",
|
||||
fret_or.status().message()));
|
||||
}
|
||||
auto fret = std::move(fret_or).ValueOrDie();
|
||||
|
||||
*new_addr = reinterpret_cast<void*>(fret.int_val);
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
::sapi::Status RPCChannel::Free(void* addr) {
|
||||
sapi::Status RPCChannel::Free(void* addr) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
uint64_t remote = reinterpret_cast<uint64_t>(addr);
|
||||
if (!comms_->SendTLV(comms::kMsgFree, sizeof(remote),
|
||||
reinterpret_cast<uint8_t*>(&remote))) {
|
||||
return ::sapi::UnavailableError("Sending TLV value failed");
|
||||
return sapi::UnavailableError("Sending TLV value failed");
|
||||
}
|
||||
|
||||
SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kVoid));
|
||||
if (!fret.success) {
|
||||
return ::sapi::UnavailableError("Free() failed on the remote side");
|
||||
return sapi::UnavailableError("Free() failed on the remote side");
|
||||
}
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
::sapi::Status RPCChannel::Symbol(const char* symname, void** addr) {
|
||||
sapi::Status RPCChannel::Symbol(const char* symname, void** addr) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
if (!comms_->SendTLV(comms::kMsgSymbol, strlen(symname) + 1,
|
||||
reinterpret_cast<const uint8_t*>(symname))) {
|
||||
return ::sapi::UnavailableError("Sending TLV value failed");
|
||||
return sapi::UnavailableError("Sending TLV value failed");
|
||||
}
|
||||
|
||||
SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kPointer));
|
||||
*addr = reinterpret_cast<void*>(fret.int_val);
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
::sapi::Status RPCChannel::Exit() {
|
||||
sapi::Status RPCChannel::Exit() {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
if (comms_->IsTerminated()) {
|
||||
VLOG(2) << "Comms channel already terminated";
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
// Try the RPC exit sequence. But, the only thing that matters as a success
|
||||
|
@ -146,62 +146,62 @@ namespace sapi {
|
|||
if (!comms_->IsTerminated()) {
|
||||
LOG(ERROR) << "Comms channel not terminated in Exit()";
|
||||
// TODO(hamacher): Better error code
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
"Comms channel not terminated in Exit()");
|
||||
}
|
||||
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
::sapi::Status RPCChannel::SendFD(int local_fd, int* remote_fd) {
|
||||
sapi::Status RPCChannel::SendFD(int local_fd, int* remote_fd) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
bool unused = true;
|
||||
if (!comms_->SendTLV(comms::kMsgSendFd, sizeof(unused),
|
||||
reinterpret_cast<uint8_t*>(&unused))) {
|
||||
return ::sapi::UnavailableError("Sending TLV value failed");
|
||||
return sapi::UnavailableError("Sending TLV value failed");
|
||||
}
|
||||
if (!comms_->SendFD(local_fd)) {
|
||||
return ::sapi::UnavailableError("Sending FD failed");
|
||||
return sapi::UnavailableError("Sending FD failed");
|
||||
}
|
||||
|
||||
SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kInt));
|
||||
if (!fret.success) {
|
||||
return ::sapi::UnavailableError("SendFD failed on the remote side");
|
||||
return sapi::UnavailableError("SendFD failed on the remote side");
|
||||
}
|
||||
*remote_fd = fret.int_val;
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
::sapi::Status RPCChannel::RecvFD(int remote_fd, int* local_fd) {
|
||||
sapi::Status RPCChannel::RecvFD(int remote_fd, int* local_fd) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
if (!comms_->SendTLV(comms::kMsgRecvFd, sizeof(remote_fd),
|
||||
reinterpret_cast<uint8_t*>(&remote_fd))) {
|
||||
return ::sapi::UnavailableError("Sending TLV value failed");
|
||||
return sapi::UnavailableError("Sending TLV value failed");
|
||||
}
|
||||
|
||||
if (!comms_->RecvFD(local_fd)) {
|
||||
return ::sapi::UnavailableError("Receving FD failed");
|
||||
return sapi::UnavailableError("Receving FD failed");
|
||||
}
|
||||
|
||||
SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kVoid));
|
||||
if (!fret.success) {
|
||||
return ::sapi::UnavailableError("RecvFD failed on the remote side");
|
||||
return sapi::UnavailableError("RecvFD failed on the remote side");
|
||||
}
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
::sapi::Status RPCChannel::Close(int remote_fd) {
|
||||
sapi::Status RPCChannel::Close(int remote_fd) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
if (!comms_->SendTLV(comms::kMsgClose, sizeof(remote_fd),
|
||||
reinterpret_cast<uint8_t*>(&remote_fd))) {
|
||||
return ::sapi::UnavailableError("Sending TLV value failed");
|
||||
return sapi::UnavailableError("Sending TLV value failed");
|
||||
}
|
||||
|
||||
SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kVoid));
|
||||
if (!fret.success) {
|
||||
return ::sapi::UnavailableError("Close() failed on the remote side");
|
||||
return sapi::UnavailableError("Close() failed on the remote side");
|
||||
}
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
} // namespace sapi
|
||||
|
|
|
@ -33,38 +33,38 @@ class RPCChannel {
|
|||
explicit RPCChannel(sandbox2::Comms* comms) : comms_(comms) {}
|
||||
|
||||
// Calls a function.
|
||||
::sapi::Status Call(const FuncCall& call, uint32_t tag, FuncRet* ret,
|
||||
v::Type exp_type);
|
||||
sapi::Status Call(const FuncCall& call, uint32_t tag, FuncRet* ret,
|
||||
v::Type exp_type);
|
||||
|
||||
// Allocates memory.
|
||||
::sapi::Status Allocate(size_t size, void** addr);
|
||||
sapi::Status Allocate(size_t size, void** addr);
|
||||
|
||||
// Reallocates memory.
|
||||
::sapi::Status Reallocate(void* old_addr, size_t size, void** new_addr);
|
||||
sapi::Status Reallocate(void* old_addr, size_t size, void** new_addr);
|
||||
|
||||
// Frees memory.
|
||||
::sapi::Status Free(void* addr);
|
||||
sapi::Status Free(void* addr);
|
||||
|
||||
// Returns address of a symbol.
|
||||
::sapi::Status Symbol(const char* symname, void** addr);
|
||||
sapi::Status Symbol(const char* symname, void** addr);
|
||||
|
||||
// Makes the remote part exit.
|
||||
::sapi::Status Exit();
|
||||
sapi::Status Exit();
|
||||
|
||||
// Transfers fd to sandboxee.
|
||||
::sapi::Status SendFD(int local_fd, int* remote_fd);
|
||||
sapi::Status SendFD(int local_fd, int* remote_fd);
|
||||
|
||||
// Retrieves fd from sandboxee.
|
||||
::sapi::Status RecvFD(int remote_fd, int* local_fd);
|
||||
sapi::Status RecvFD(int remote_fd, int* local_fd);
|
||||
|
||||
// Closes fd in sandboxee.
|
||||
::sapi::Status Close(int remote_fd);
|
||||
sapi::Status Close(int remote_fd);
|
||||
|
||||
sandbox2::Comms* comms() const { return comms_; }
|
||||
|
||||
private:
|
||||
// Receives the result after a call.
|
||||
::sapi::StatusOr<FuncRet> Return(v::Type exp_type);
|
||||
sapi::StatusOr<FuncRet> Return(v::Type exp_type);
|
||||
|
||||
sandbox2::Comms* comms_; // Owned by sandbox2;
|
||||
absl::Mutex mutex_;
|
||||
|
|
|
@ -128,10 +128,10 @@ static std::string PathToSAPILib(const std::string& lib_path) {
|
|||
: sandbox2::GetDataDependencyFilePath(lib_path);
|
||||
}
|
||||
|
||||
::sapi::Status Sandbox::Init() {
|
||||
sapi::Status Sandbox::Init() {
|
||||
// It's already initialized
|
||||
if (IsActive()) {
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
// Initialize the forkserver if it is not already running.
|
||||
|
@ -146,14 +146,14 @@ static std::string PathToSAPILib(const std::string& lib_path) {
|
|||
if (embed_lib_fd == -1) {
|
||||
PLOG(ERROR) << "Cannot create executable FD for TOC:'"
|
||||
<< embed_lib_toc_->name << "'";
|
||||
return ::sapi::UnavailableError("Could not create executable FD");
|
||||
return sapi::UnavailableError("Could not create executable FD");
|
||||
}
|
||||
lib_path = embed_lib_toc_->name;
|
||||
} else {
|
||||
lib_path = PathToSAPILib(GetLibPath());
|
||||
if (lib_path.empty()) {
|
||||
LOG(ERROR) << "SAPI library path is empty";
|
||||
return ::sapi::FailedPreconditionError("No SAPI library path given");
|
||||
return sapi::FailedPreconditionError("No SAPI library path given");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,7 +173,7 @@ static std::string PathToSAPILib(const std::string& lib_path) {
|
|||
|
||||
if (!fork_client_) {
|
||||
LOG(ERROR) << "Could not start forkserver";
|
||||
return ::sapi::UnavailableError("Could not start the forkserver");
|
||||
return sapi::UnavailableError("Could not start the forkserver");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -210,38 +210,38 @@ static std::string PathToSAPILib(const std::string& lib_path) {
|
|||
|
||||
if (!res) {
|
||||
Terminate();
|
||||
return ::sapi::UnavailableError("Could not start the sandbox");
|
||||
return sapi::UnavailableError("Could not start the sandbox");
|
||||
}
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
bool Sandbox::IsActive() const { return s2_ && !s2_->IsTerminated(); }
|
||||
|
||||
::sapi::Status Sandbox::Allocate(v::Var* var, bool automatic_free) {
|
||||
sapi::Status Sandbox::Allocate(v::Var* var, bool automatic_free) {
|
||||
if (!IsActive()) {
|
||||
return ::sapi::UnavailableError("Sandbox not active");
|
||||
return sapi::UnavailableError("Sandbox not active");
|
||||
}
|
||||
return var->Allocate(GetRpcChannel(), automatic_free);
|
||||
}
|
||||
|
||||
::sapi::Status Sandbox::Free(v::Var* var) {
|
||||
sapi::Status Sandbox::Free(v::Var* var) {
|
||||
if (!IsActive()) {
|
||||
return ::sapi::UnavailableError("Sandbox not active");
|
||||
return sapi::UnavailableError("Sandbox not active");
|
||||
}
|
||||
return var->Free(GetRpcChannel());
|
||||
}
|
||||
|
||||
::sapi::Status Sandbox::SynchronizePtrBefore(v::Callable* ptr) {
|
||||
sapi::Status Sandbox::SynchronizePtrBefore(v::Callable* ptr) {
|
||||
if (!IsActive()) {
|
||||
return ::sapi::UnavailableError("Sandbox not active");
|
||||
return sapi::UnavailableError("Sandbox not active");
|
||||
}
|
||||
if (ptr->GetType() != v::Type::kPointer) {
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
// Cast is safe, since type is v::Type::kPointer
|
||||
auto* p = static_cast<v::Ptr*>(ptr);
|
||||
if (p->GetSyncType() == v::Pointable::SYNC_NONE) {
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
if (p->GetPointedVar()->GetRemote() == nullptr) {
|
||||
|
@ -254,7 +254,7 @@ bool Sandbox::IsActive() const { return s2_ && !s2_->IsTerminated(); }
|
|||
// memory is transferred to the sandboxee only if v::Pointable::SYNC_BEFORE
|
||||
// was requested.
|
||||
if ((p->GetSyncType() & v::Pointable::SYNC_BEFORE) == 0) {
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
VLOG(3) << "Synchronization (TO), ptr " << p << ", Type: " << p->GetSyncType()
|
||||
|
@ -263,16 +263,16 @@ bool Sandbox::IsActive() const { return s2_ && !s2_->IsTerminated(); }
|
|||
return p->GetPointedVar()->TransferToSandboxee(GetRpcChannel(), GetPid());
|
||||
}
|
||||
|
||||
::sapi::Status Sandbox::SynchronizePtrAfter(v::Callable* ptr) const {
|
||||
sapi::Status Sandbox::SynchronizePtrAfter(v::Callable* ptr) const {
|
||||
if (!IsActive()) {
|
||||
return ::sapi::UnavailableError("Sandbox not active");
|
||||
return sapi::UnavailableError("Sandbox not active");
|
||||
}
|
||||
if (ptr->GetType() != v::Type::kPointer) {
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
v::Ptr* p = reinterpret_cast<v::Ptr*>(ptr);
|
||||
if ((p->GetSyncType() & v::Pointable::SYNC_AFTER) == 0) {
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
VLOG(3) << "Synchronization (FROM), ptr " << p
|
||||
|
@ -282,7 +282,7 @@ bool Sandbox::IsActive() const { return s2_ && !s2_->IsTerminated(); }
|
|||
if (p->GetPointedVar()->GetRemote() == nullptr) {
|
||||
LOG(ERROR) << "Trying to synchronize a variable which is not allocated in "
|
||||
<< "the sandboxee p=" << p->ToString();
|
||||
return ::sapi::FailedPreconditionError(absl::StrCat(
|
||||
return sapi::FailedPreconditionError(absl::StrCat(
|
||||
"Trying to synchronize a variable which is not allocated in the "
|
||||
"sandboxee p=",
|
||||
p->ToString()));
|
||||
|
@ -291,10 +291,10 @@ bool Sandbox::IsActive() const { return s2_ && !s2_->IsTerminated(); }
|
|||
return p->GetPointedVar()->TransferFromSandboxee(GetRpcChannel(), GetPid());
|
||||
}
|
||||
|
||||
::sapi::Status Sandbox::Call(const std::string& func, v::Callable* ret,
|
||||
std::initializer_list<v::Callable*> args) {
|
||||
sapi::Status Sandbox::Call(const std::string& func, v::Callable* ret,
|
||||
std::initializer_list<v::Callable*> args) {
|
||||
if (!IsActive()) {
|
||||
return ::sapi::UnavailableError("Sandbox not active");
|
||||
return sapi::UnavailableError("Sandbox not active");
|
||||
}
|
||||
// Send data.
|
||||
FuncCall rfcall{};
|
||||
|
@ -368,26 +368,26 @@ bool Sandbox::IsActive() const { return s2_ && !s2_->IsTerminated(); }
|
|||
VLOG(1) << "CALL EXIT: Type: " << ret->GetTypeString()
|
||||
<< ", Size: " << ret->GetSize() << ", Val: " << ret->ToString();
|
||||
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
::sapi::Status Sandbox::Symbol(const char* symname, void** addr) {
|
||||
sapi::Status Sandbox::Symbol(const char* symname, void** addr) {
|
||||
if (!IsActive()) {
|
||||
return ::sapi::UnavailableError("Sandbox not active");
|
||||
return sapi::UnavailableError("Sandbox not active");
|
||||
}
|
||||
return rpc_channel_->Symbol(symname, addr);
|
||||
}
|
||||
|
||||
::sapi::Status Sandbox::TransferToSandboxee(v::Var* var) {
|
||||
sapi::Status Sandbox::TransferToSandboxee(v::Var* var) {
|
||||
if (!IsActive()) {
|
||||
return ::sapi::UnavailableError("Sandbox not active");
|
||||
return sapi::UnavailableError("Sandbox not active");
|
||||
}
|
||||
return var->TransferToSandboxee(GetRpcChannel(), GetPid());
|
||||
}
|
||||
|
||||
::sapi::Status Sandbox::TransferFromSandboxee(v::Var* var) {
|
||||
sapi::Status Sandbox::TransferFromSandboxee(v::Var* var) {
|
||||
if (!IsActive()) {
|
||||
return ::sapi::UnavailableError("Sandbox not active");
|
||||
return sapi::UnavailableError("Sandbox not active");
|
||||
}
|
||||
return var->TransferFromSandboxee(GetRpcChannel(), GetPid());
|
||||
}
|
||||
|
@ -400,12 +400,12 @@ const sandbox2::Result& Sandbox::AwaitResult() {
|
|||
return result_;
|
||||
}
|
||||
|
||||
::sapi::Status Sandbox::SetWallTimeLimit(time_t limit) const {
|
||||
sapi::Status Sandbox::SetWallTimeLimit(time_t limit) const {
|
||||
if (!IsActive()) {
|
||||
return ::sapi::UnavailableError("Sandbox not active");
|
||||
return sapi::UnavailableError("Sandbox not active");
|
||||
}
|
||||
s2_->SetWallTimeLimit(limit);
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
void Sandbox::Exit() const {
|
||||
|
|
|
@ -43,7 +43,7 @@ class Sandbox {
|
|||
virtual ~Sandbox();
|
||||
|
||||
// Initializes a new sandboxing session.
|
||||
::sapi::Status Init();
|
||||
sapi::Status Init();
|
||||
|
||||
// Is the current sandboxing session alive?
|
||||
bool IsActive() const;
|
||||
|
@ -52,7 +52,7 @@ class Sandbox {
|
|||
void Terminate(bool attempt_graceful_exit = true);
|
||||
|
||||
// Restarts the sandbox.
|
||||
::sapi::Status Restart(bool attempt_graceful_exit) {
|
||||
sapi::Status Restart(bool attempt_graceful_exit) {
|
||||
Terminate(attempt_graceful_exit);
|
||||
return Init();
|
||||
}
|
||||
|
@ -65,42 +65,41 @@ class Sandbox {
|
|||
int GetPid() const { return pid_; }
|
||||
|
||||
// Synchronizes the underlying memory for the pointer before the call.
|
||||
::sapi::Status SynchronizePtrBefore(v::Callable* ptr);
|
||||
sapi::Status SynchronizePtrBefore(v::Callable* ptr);
|
||||
|
||||
// Synchronizes the underlying memory for pointer after the call.
|
||||
::sapi::Status SynchronizePtrAfter(v::Callable* ptr) const;
|
||||
sapi::Status SynchronizePtrAfter(v::Callable* ptr) const;
|
||||
|
||||
// Makes a call to the sandboxee.
|
||||
template <typename... Args>
|
||||
::sapi::Status Call(const std::string& func, v::Callable* ret,
|
||||
Args&&... args) {
|
||||
sapi::Status Call(const std::string& func, v::Callable* ret, Args&&... args) {
|
||||
static_assert(sizeof...(Args) <= FuncCall::kArgsMax,
|
||||
"Too many arguments to sapi::Sandbox::Call()");
|
||||
return Call(func, ret, {std::forward<Args>(args)...});
|
||||
}
|
||||
::sapi::Status Call(const std::string& func, v::Callable* ret,
|
||||
std::initializer_list<v::Callable*> args);
|
||||
sapi::Status Call(const std::string& func, v::Callable* ret,
|
||||
std::initializer_list<v::Callable*> args);
|
||||
|
||||
// Allocates memory in the sandboxee, automatic_free indicates whether the
|
||||
// memory should be freed on the remote side when the 'var' goes out of scope.
|
||||
::sapi::Status Allocate(v::Var* var, bool automatic_free = false);
|
||||
sapi::Status Allocate(v::Var* var, bool automatic_free = false);
|
||||
|
||||
// Frees memory in the sandboxee.
|
||||
::sapi::Status Free(v::Var* var);
|
||||
sapi::Status Free(v::Var* var);
|
||||
|
||||
// Finds address of a symbol in the sandboxee.
|
||||
::sapi::Status Symbol(const char* symname, void** addr);
|
||||
sapi::Status Symbol(const char* symname, void** addr);
|
||||
|
||||
// Transfers memory (both directions). Status is returned (memory transfer
|
||||
// succeeded/failed).
|
||||
::sapi::Status TransferToSandboxee(v::Var* var);
|
||||
::sapi::Status TransferFromSandboxee(v::Var* var);
|
||||
sapi::Status TransferToSandboxee(v::Var* var);
|
||||
sapi::Status TransferFromSandboxee(v::Var* var);
|
||||
|
||||
// Waits until the sandbox terminated and returns the result.
|
||||
const sandbox2::Result& AwaitResult();
|
||||
const sandbox2::Result& result() const { return result_; }
|
||||
|
||||
::sapi::Status SetWallTimeLimit(time_t limit) const;
|
||||
sapi::Status SetWallTimeLimit(time_t limit) const;
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
@ -29,12 +29,12 @@
|
|||
namespace sandbox2 {
|
||||
|
||||
// Creates a new Buffer that is backed by the specified file descriptor.
|
||||
::sapi::StatusOr<std::unique_ptr<Buffer>> Buffer::CreateFromFd(int fd) {
|
||||
sapi::StatusOr<std::unique_ptr<Buffer>> Buffer::CreateFromFd(int fd) {
|
||||
auto buffer = absl::WrapUnique(new Buffer{});
|
||||
|
||||
struct stat stat_buf;
|
||||
if (fstat(fd, &stat_buf) != 0) {
|
||||
return ::sapi::InternalError(
|
||||
return sapi::InternalError(
|
||||
absl::StrCat("Could not stat buffer fd: ", StrError(errno)));
|
||||
}
|
||||
size_t size = stat_buf.st_size;
|
||||
|
@ -44,7 +44,7 @@ namespace sandbox2 {
|
|||
buffer->buf_ =
|
||||
reinterpret_cast<uint8_t*>(mmap(nullptr, size, prot, flags, fd, offset));
|
||||
if (buffer->buf_ == MAP_FAILED) {
|
||||
return ::sapi::InternalError(
|
||||
return sapi::InternalError(
|
||||
absl::StrCat("Could not map buffer fd: ", StrError(errno)));
|
||||
}
|
||||
buffer->fd_ = fd;
|
||||
|
@ -54,13 +54,13 @@ namespace sandbox2 {
|
|||
|
||||
// Creates a new Buffer of the specified size, backed by a temporary file that
|
||||
// will be immediately deleted.
|
||||
::sapi::StatusOr<std::unique_ptr<Buffer>> Buffer::CreateWithSize(int64_t size) {
|
||||
sapi::StatusOr<std::unique_ptr<Buffer>> Buffer::CreateWithSize(int64_t size) {
|
||||
int fd;
|
||||
if (!util::CreateMemFd(&fd)) {
|
||||
return ::sapi::InternalError("Could not create buffer temp file");
|
||||
return sapi::InternalError("Could not create buffer temp file");
|
||||
}
|
||||
if (ftruncate(fd, size) != 0) {
|
||||
return ::sapi::InternalError(
|
||||
return sapi::InternalError(
|
||||
absl::StrCat("Could not extend buffer fd: ", StrError(errno)));
|
||||
}
|
||||
return CreateFromFd(fd);
|
||||
|
|
|
@ -37,11 +37,11 @@ class Buffer final {
|
|||
// Creates a new Buffer that is backed by the specified file descriptor.
|
||||
// The Buffer takes ownership of the descriptor and will close it when
|
||||
// destroyed.
|
||||
static ::sapi::StatusOr<std::unique_ptr<Buffer>> CreateFromFd(int fd);
|
||||
static sapi::StatusOr<std::unique_ptr<Buffer>> CreateFromFd(int fd);
|
||||
|
||||
// Creates a new Buffer of the specified size, backed by a temporary file that
|
||||
// will be immediately deleted.
|
||||
static ::sapi::StatusOr<std::unique_ptr<Buffer>> CreateWithSize(int64_t size);
|
||||
static sapi::StatusOr<std::unique_ptr<Buffer>> CreateWithSize(int64_t size);
|
||||
|
||||
// Returns a pointer to the buffer, which is read/write.
|
||||
uint8_t* data() const { return buf_; }
|
||||
|
|
|
@ -308,7 +308,7 @@ TEST_F(CommsTest, TestSendRecvStatusOK) {
|
|||
};
|
||||
auto b = [](Comms* comms) {
|
||||
// Send a good status.
|
||||
ASSERT_THAT(comms->SendStatus(::sapi::OkStatus()), IsTrue());
|
||||
ASSERT_THAT(comms->SendStatus(sapi::OkStatus()), IsTrue());
|
||||
};
|
||||
HandleCommunication(sockname_, a, b);
|
||||
}
|
||||
|
|
|
@ -133,19 +133,19 @@ void RunInitProcess(std::set<int> open_fds) {
|
|||
}
|
||||
}
|
||||
|
||||
::sapi::Status SendPid(int signaling_fd) {
|
||||
sapi::Status SendPid(int signaling_fd) {
|
||||
// Send our PID (the actual sandboxee process) via SCM_CREDENTIALS.
|
||||
// The ancillary message will be attached to the message as SO_PASSCRED is set
|
||||
// on the socket.
|
||||
char dummy = ' ';
|
||||
if (TEMP_FAILURE_RETRY(send(signaling_fd, &dummy, 1, 0)) != 1) {
|
||||
return ::sapi::InternalError(
|
||||
return sapi::InternalError(
|
||||
absl::StrCat("Sending PID: send: ", sandbox2::StrError(errno)));
|
||||
}
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
::sapi::StatusOr<pid_t> ReceivePid(int signaling_fd) {
|
||||
sapi::StatusOr<pid_t> ReceivePid(int signaling_fd) {
|
||||
union {
|
||||
struct cmsghdr cmh;
|
||||
char ctrl[CMSG_SPACE(sizeof(struct ucred))];
|
||||
|
@ -164,13 +164,13 @@ void RunInitProcess(std::set<int> open_fds) {
|
|||
iov.iov_len = sizeof(char);
|
||||
|
||||
if (TEMP_FAILURE_RETRY(recvmsg(signaling_fd, &msgh, MSG_WAITALL)) != 1) {
|
||||
return ::sapi::InternalError(absl::StrCat("Receiving pid failed: recvmsg: ",
|
||||
sandbox2::StrError(errno)));
|
||||
return sapi::InternalError(absl::StrCat("Receiving pid failed: recvmsg: ",
|
||||
sandbox2::StrError(errno)));
|
||||
}
|
||||
struct cmsghdr* cmsgp = CMSG_FIRSTHDR(&msgh);
|
||||
if (cmsgp->cmsg_len != CMSG_LEN(sizeof(struct ucred)) ||
|
||||
cmsgp->cmsg_level != SOL_SOCKET || cmsgp->cmsg_type != SCM_CREDENTIALS) {
|
||||
return ::sapi::InternalError("Receiving pid failed");
|
||||
return sapi::InternalError("Receiving pid failed");
|
||||
}
|
||||
struct ucred* ucredp = reinterpret_cast<struct ucred*>(CMSG_DATA(cmsgp));
|
||||
return ucredp->pid;
|
||||
|
|
|
@ -97,15 +97,14 @@ absl::string_view GetOutsidePath(const MountTree::Node& node) {
|
|||
}
|
||||
}
|
||||
|
||||
::sapi::StatusOr<std::string> ExistingPathInsideDir(
|
||||
sapi::StatusOr<std::string> ExistingPathInsideDir(
|
||||
absl::string_view dir_path, absl::string_view relative_path) {
|
||||
auto path = file::CleanPath(file::JoinPath(dir_path, relative_path));
|
||||
if (file_util::fileops::StripBasename(path) != dir_path) {
|
||||
return ::sapi::InvalidArgumentError(
|
||||
"Relative path goes above the base dir");
|
||||
return sapi::InvalidArgumentError("Relative path goes above the base dir");
|
||||
}
|
||||
if (!file_util::fileops::Exists(path, false)) {
|
||||
return ::sapi::NotFoundError(absl::StrCat("Does not exist: ", path));
|
||||
return sapi::NotFoundError(absl::StrCat("Does not exist: ", path));
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
@ -116,10 +115,10 @@ sapi::Status ValidateInterpreter(absl::string_view interpreter) {
|
|||
};
|
||||
|
||||
if (!allowed_interpreters.contains(interpreter)) {
|
||||
return ::sapi::InvalidArgumentError(
|
||||
return sapi::InvalidArgumentError(
|
||||
absl::StrCat("Interpreter not on the whitelist: ", interpreter));
|
||||
}
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
std::string ResolveLibraryPath(absl::string_view lib_name,
|
||||
|
@ -146,8 +145,8 @@ std::string GetPlatform(absl::string_view interpreter) {
|
|||
|
||||
} // namespace
|
||||
|
||||
::sapi::Status Mounts::Insert(absl::string_view path,
|
||||
const MountTree::Node& new_node) {
|
||||
sapi::Status Mounts::Insert(absl::string_view path,
|
||||
const MountTree::Node& new_node) {
|
||||
// Some sandboxes allow the inside/outside paths to be partially
|
||||
// user-controlled with some sanitization.
|
||||
// Since we're handling C++ strings and later convert them to C style
|
||||
|
@ -155,7 +154,7 @@ std::string GetPlatform(absl::string_view interpreter) {
|
|||
// and mount something not expected by the caller. Check for null bytes in the
|
||||
// strings to protect against this.
|
||||
if (PathContainsNullByte(path)) {
|
||||
return ::sapi::InvalidArgumentError(
|
||||
return sapi::InvalidArgumentError(
|
||||
absl::StrCat("Inside path contains a null byte: ", path));
|
||||
}
|
||||
switch (new_node.node_case()) {
|
||||
|
@ -163,10 +162,10 @@ std::string GetPlatform(absl::string_view interpreter) {
|
|||
case MountTree::Node::kDirNode: {
|
||||
auto outside_path = GetOutsidePath(new_node);
|
||||
if (outside_path.empty()) {
|
||||
return ::sapi::InvalidArgumentError("Outside path cannot be empty");
|
||||
return sapi::InvalidArgumentError("Outside path cannot be empty");
|
||||
}
|
||||
if (PathContainsNullByte(outside_path)) {
|
||||
return ::sapi::InvalidArgumentError(
|
||||
return sapi::InvalidArgumentError(
|
||||
absl::StrCat("Outside path contains a null byte: ", outside_path));
|
||||
}
|
||||
break;
|
||||
|
@ -179,11 +178,11 @@ std::string GetPlatform(absl::string_view interpreter) {
|
|||
std::string fixed_path = file::CleanPath(path);
|
||||
|
||||
if (!absl::StartsWith(fixed_path, "/")) {
|
||||
return ::sapi::InvalidArgumentError("Only absolute paths are supported");
|
||||
return sapi::InvalidArgumentError("Only absolute paths are supported");
|
||||
}
|
||||
|
||||
if (fixed_path == "/") {
|
||||
return ::sapi::InvalidArgumentError("The root already exists");
|
||||
return sapi::InvalidArgumentError("The root already exists");
|
||||
}
|
||||
|
||||
std::vector<absl::string_view> parts;
|
||||
|
@ -204,7 +203,7 @@ std::string GetPlatform(absl::string_view interpreter) {
|
|||
->insert({std::string(*part), MountTree()})
|
||||
.first->second);
|
||||
if (curtree->has_node() && curtree->node().has_file_node()) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
absl::StrCat("Cannot insert ", path,
|
||||
" since a file is mounted as a parent directory"));
|
||||
}
|
||||
|
@ -217,28 +216,28 @@ std::string GetPlatform(absl::string_view interpreter) {
|
|||
if (curtree->has_node()) {
|
||||
if (IsEquivalentNode(curtree->node(), new_node)) {
|
||||
SAPI_RAW_LOG(INFO, "Inserting %s with the same value twice", path);
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
return ::sapi::FailedPreconditionError(absl::StrCat(
|
||||
return sapi::FailedPreconditionError(absl::StrCat(
|
||||
"Inserting ", path, " twice with conflicting values ",
|
||||
curtree->node().DebugString(), " vs. ", new_node.DebugString()));
|
||||
}
|
||||
|
||||
if (new_node.has_file_node() && !curtree->entries().empty()) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
absl::StrCat("Trying to mount file over existing directory at ", path));
|
||||
}
|
||||
|
||||
*curtree->mutable_node() = new_node;
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
::sapi::Status Mounts::AddFile(absl::string_view path, bool is_ro) {
|
||||
sapi::Status Mounts::AddFile(absl::string_view path, bool is_ro) {
|
||||
return AddFileAt(path, path, is_ro);
|
||||
}
|
||||
|
||||
::sapi::Status Mounts::AddFileAt(absl::string_view outside,
|
||||
absl::string_view inside, bool is_ro) {
|
||||
sapi::Status Mounts::AddFileAt(absl::string_view outside,
|
||||
absl::string_view inside, bool is_ro) {
|
||||
MountTree::Node node;
|
||||
auto* file_node = node.mutable_file_node();
|
||||
file_node->set_outside(std::string(outside));
|
||||
|
@ -246,8 +245,8 @@ std::string GetPlatform(absl::string_view interpreter) {
|
|||
return Insert(inside, node);
|
||||
}
|
||||
|
||||
::sapi::Status Mounts::AddDirectoryAt(absl::string_view outside,
|
||||
absl::string_view inside, bool is_ro) {
|
||||
sapi::Status Mounts::AddDirectoryAt(absl::string_view outside,
|
||||
absl::string_view inside, bool is_ro) {
|
||||
MountTree::Node node;
|
||||
auto dir_node = node.mutable_dir_node();
|
||||
dir_node->set_outside(std::string(outside));
|
||||
|
@ -265,12 +264,12 @@ void LogContainer(const std::vector<std::string>& container) {
|
|||
|
||||
} // namespace
|
||||
|
||||
::sapi::Status Mounts::AddMappingsForBinary(const std::string& path,
|
||||
absl::string_view ld_library_path) {
|
||||
sapi::Status Mounts::AddMappingsForBinary(const std::string& path,
|
||||
absl::string_view ld_library_path) {
|
||||
auto elf_or = ElfFile::ParseFromFile(
|
||||
path, ElfFile::kGetInterpreter | ElfFile::kLoadImportedLibraries);
|
||||
if (!elf_or.ok()) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
absl::StrCat("Could not parse ELF file: ", elf_or.status().message()));
|
||||
}
|
||||
auto elf = elf_or.ValueOrDie();
|
||||
|
@ -278,7 +277,7 @@ void LogContainer(const std::vector<std::string>& container) {
|
|||
|
||||
if (interpreter.empty()) {
|
||||
SAPI_RAW_VLOG(1, "The file %s is not a dynamic executable", path);
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
SAPI_RAW_VLOG(1, "The file %s is using interpreter %s", path, interpreter);
|
||||
|
@ -331,7 +330,7 @@ void LogContainer(const std::vector<std::string>& container) {
|
|||
{
|
||||
auto imported_libs = elf.imported_libraries();
|
||||
if (imported_libs.size() > kMaxWorkQueueSize) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
"Exceeded max entries pending resolving limit");
|
||||
}
|
||||
for (const auto& imported_lib : imported_libs) {
|
||||
|
@ -360,11 +359,11 @@ void LogContainer(const std::vector<std::string>& container) {
|
|||
to_resolve.pop_back();
|
||||
++resolved;
|
||||
if (resolved > kMaxResolvedEntries) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
"Exceeded max resolved entries limit");
|
||||
}
|
||||
if (depth > kMaxResolvingDepth) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
"Exceeded max resolving depth limit");
|
||||
}
|
||||
std::string resolved_lib = ResolveLibraryPath(lib, full_search_paths);
|
||||
|
@ -380,20 +379,19 @@ void LogContainer(const std::vector<std::string>& container) {
|
|||
|
||||
imported_libraries.insert(resolved_lib);
|
||||
if (imported_libraries.size() > kMaxImportedLibraries) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
"Exceeded max imported libraries limit");
|
||||
}
|
||||
++loaded;
|
||||
if (loaded > kMaxLoadedEntries) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
"Exceeded max loaded entries limit");
|
||||
return sapi::FailedPreconditionError("Exceeded max loaded entries limit");
|
||||
}
|
||||
SAPI_ASSIGN_OR_RETURN(
|
||||
auto lib_elf,
|
||||
ElfFile::ParseFromFile(resolved_lib, ElfFile::kLoadImportedLibraries));
|
||||
auto imported_libs = lib_elf.imported_libraries();
|
||||
if (imported_libs.size() > kMaxWorkQueueSize - to_resolve.size()) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
"Exceeded max entries pending resolving limit");
|
||||
}
|
||||
|
||||
|
@ -414,10 +412,10 @@ void LogContainer(const std::vector<std::string>& container) {
|
|||
SAPI_RETURN_IF_ERROR(AddFile(lib));
|
||||
}
|
||||
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
::sapi::Status Mounts::AddTmpfs(absl::string_view inside, size_t sz) {
|
||||
sapi::Status Mounts::AddTmpfs(absl::string_view inside, size_t sz) {
|
||||
MountTree::Node node;
|
||||
auto tmpfs_node = node.mutable_tmpfs_node();
|
||||
tmpfs_node->set_tmpfs_options(absl::StrCat("size=", sz));
|
||||
|
|
|
@ -30,18 +30,18 @@ class Mounts {
|
|||
Mounts() = default;
|
||||
explicit Mounts(MountTree mount_tree) : mount_tree_(std::move(mount_tree)) {}
|
||||
|
||||
::sapi::Status AddFile(absl::string_view path, bool is_ro = true);
|
||||
sapi::Status AddFile(absl::string_view path, bool is_ro = true);
|
||||
|
||||
::sapi::Status AddFileAt(absl::string_view outside, absl::string_view inside,
|
||||
bool is_ro = true);
|
||||
sapi::Status AddFileAt(absl::string_view outside, absl::string_view inside,
|
||||
bool is_ro = true);
|
||||
|
||||
::sapi::Status AddDirectoryAt(absl::string_view outside,
|
||||
absl::string_view inside, bool is_ro = true);
|
||||
sapi::Status AddDirectoryAt(absl::string_view outside,
|
||||
absl::string_view inside, bool is_ro = true);
|
||||
|
||||
::sapi::Status AddMappingsForBinary(const std::string& path,
|
||||
absl::string_view ld_library_path = {});
|
||||
sapi::Status AddMappingsForBinary(const std::string& path,
|
||||
absl::string_view ld_library_path = {});
|
||||
|
||||
::sapi::Status AddTmpfs(absl::string_view inside, size_t sz);
|
||||
sapi::Status AddTmpfs(absl::string_view inside, size_t sz);
|
||||
|
||||
void CreateMounts(const std::string& root_path) const;
|
||||
|
||||
|
@ -59,7 +59,7 @@ class Mounts {
|
|||
|
||||
private:
|
||||
friend class MountTreeTest;
|
||||
::sapi::Status Insert(absl::string_view path, const MountTree::Node& node);
|
||||
sapi::Status Insert(absl::string_view path, const MountTree::Node& node);
|
||||
MountTree mount_tree_;
|
||||
};
|
||||
|
||||
|
|
|
@ -634,20 +634,20 @@ PolicyBuilder& PolicyBuilder::DangerDefaultAllowAll() {
|
|||
return *this;
|
||||
}
|
||||
|
||||
::sapi::StatusOr<std::string> PolicyBuilder::ValidateAbsolutePath(
|
||||
sapi::StatusOr<std::string> PolicyBuilder::ValidateAbsolutePath(
|
||||
absl::string_view path) {
|
||||
if (!file::IsAbsolutePath(path)) {
|
||||
return ::sapi::InvalidArgumentError(
|
||||
return sapi::InvalidArgumentError(
|
||||
absl::StrCat("Path is not absolute: '", path, "'"));
|
||||
}
|
||||
return ValidatePath(path);
|
||||
}
|
||||
|
||||
::sapi::StatusOr<std::string> PolicyBuilder::ValidatePath(
|
||||
sapi::StatusOr<std::string> PolicyBuilder::ValidatePath(
|
||||
absl::string_view path) {
|
||||
std::string fixed_path = file::CleanPath(path);
|
||||
if (fixed_path != path) {
|
||||
return ::sapi::InvalidArgumentError(absl::StrCat(
|
||||
return sapi::InvalidArgumentError(absl::StrCat(
|
||||
"Path was not normalized. '", path, "' != '", fixed_path, "'"));
|
||||
}
|
||||
return fixed_path;
|
||||
|
@ -658,13 +658,13 @@ std::vector<sock_filter> PolicyBuilder::ResolveBpfFunc(BpfFunc f) {
|
|||
|
||||
std::vector<sock_filter> policy = f(l);
|
||||
if (bpf_resolve_jumps(&l, policy.data(), policy.size()) != 0) {
|
||||
SetError(::sapi::InternalError("Cannot resolve bpf jumps"));
|
||||
SetError(sapi::InternalError("Cannot resolve bpf jumps"));
|
||||
}
|
||||
|
||||
return policy;
|
||||
}
|
||||
|
||||
::sapi::StatusOr<std::unique_ptr<Policy>> PolicyBuilder::TryBuild() {
|
||||
sapi::StatusOr<std::unique_ptr<Policy>> PolicyBuilder::TryBuild() {
|
||||
CHECK_NE(use_namespaces_, disable_namespaces_)
|
||||
<< "Namespaces should either be enabled (by calling EnableNamespaces(), "
|
||||
"AddFile(), etc.) or disabled (by calling DisableNamespaces())";
|
||||
|
@ -673,12 +673,12 @@ std::vector<sock_filter> PolicyBuilder::ResolveBpfFunc(BpfFunc f) {
|
|||
}
|
||||
|
||||
if (!output_) {
|
||||
return ::sapi::FailedPreconditionError("Can only build policy once.");
|
||||
return sapi::FailedPreconditionError("Can only build policy once.");
|
||||
}
|
||||
|
||||
if (use_namespaces_) {
|
||||
if (allow_unrestricted_networking_ && hostname_ != kDefaultHostname) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
"Cannot set hostname without network namespaces.");
|
||||
}
|
||||
output_->SetNamespace(absl::make_unique<Namespace>(
|
||||
|
@ -706,7 +706,7 @@ PolicyBuilder& PolicyBuilder::AddFile(absl::string_view path, bool is_ro) {
|
|||
return AddFileAt(path, path, is_ro);
|
||||
}
|
||||
|
||||
PolicyBuilder& PolicyBuilder::SetError(const ::sapi::Status& status) {
|
||||
PolicyBuilder& PolicyBuilder::SetError(const sapi::Status& status) {
|
||||
LOG(ERROR) << status;
|
||||
last_status_ = status;
|
||||
return *this;
|
||||
|
@ -724,7 +724,7 @@ PolicyBuilder& PolicyBuilder::AddFileAt(absl::string_view outside,
|
|||
auto fixed_outside = std::move(fixed_outside_or.ValueOrDie());
|
||||
|
||||
if (absl::StartsWith(fixed_outside, "/proc/self")) {
|
||||
SetError(::sapi::InvalidArgumentError(
|
||||
SetError(sapi::InvalidArgumentError(
|
||||
absl::StrCat("Cannot add /proc/self mounts, you need to mount the "
|
||||
"whole /proc instead. You tried to mount ",
|
||||
outside)));
|
||||
|
@ -733,9 +733,9 @@ PolicyBuilder& PolicyBuilder::AddFileAt(absl::string_view outside,
|
|||
|
||||
auto status = mounts_.AddFileAt(fixed_outside, inside, is_ro);
|
||||
if (!status.ok()) {
|
||||
SetError(::sapi::InternalError(absl::StrCat("Could not add file ", outside,
|
||||
" => ", inside, ": ",
|
||||
status.message())));
|
||||
SetError(
|
||||
sapi::InternalError(absl::StrCat("Could not add file ", outside, " => ",
|
||||
inside, ": ", status.message())));
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
@ -754,7 +754,7 @@ PolicyBuilder& PolicyBuilder::AddLibrariesForBinary(
|
|||
|
||||
auto status = mounts_.AddMappingsForBinary(fixed_path, ld_library_path);
|
||||
if (!status.ok()) {
|
||||
SetError(::sapi::InternalError(absl::StrCat(
|
||||
SetError(sapi::InternalError(absl::StrCat(
|
||||
"Could not add libraries for ", fixed_path, ": ", status.message())));
|
||||
}
|
||||
return *this;
|
||||
|
@ -782,7 +782,7 @@ PolicyBuilder& PolicyBuilder::AddDirectoryAt(absl::string_view outside,
|
|||
}
|
||||
auto fixed_outside = std::move(fixed_outside_or.ValueOrDie());
|
||||
if (absl::StartsWith(fixed_outside, "/proc/self")) {
|
||||
SetError(::sapi::InvalidArgumentError(
|
||||
SetError(sapi::InvalidArgumentError(
|
||||
absl::StrCat("Cannot add /proc/self mounts, you need to mount the "
|
||||
"whole /proc instead. You tried to mount ",
|
||||
outside)));
|
||||
|
@ -791,9 +791,9 @@ PolicyBuilder& PolicyBuilder::AddDirectoryAt(absl::string_view outside,
|
|||
|
||||
auto status = mounts_.AddDirectoryAt(fixed_outside, inside, is_ro);
|
||||
if (!status.ok()) {
|
||||
SetError(::sapi::InternalError(absl::StrCat("Could not add directory ",
|
||||
outside, " => ", inside, ": ",
|
||||
status.message())));
|
||||
SetError(sapi::InternalError(absl::StrCat("Could not add directory ",
|
||||
outside, " => ", inside, ": ",
|
||||
status.message())));
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
@ -804,8 +804,8 @@ PolicyBuilder& PolicyBuilder::AddTmpfs(absl::string_view inside, size_t sz) {
|
|||
|
||||
auto status = mounts_.AddTmpfs(inside, sz);
|
||||
if (!status.ok()) {
|
||||
SetError(::sapi::InternalError(absl::StrCat(
|
||||
"Could not mount tmpfs ", inside, ": ", status.message())));
|
||||
SetError(sapi::InternalError(absl::StrCat("Could not mount tmpfs ", inside,
|
||||
": ", status.message())));
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
|
|
@ -388,7 +388,7 @@ class PolicyBuilder final {
|
|||
|
||||
// Builds the policy returning a unique_ptr to it. This should only be called
|
||||
// once.
|
||||
::sapi::StatusOr<std::unique_ptr<Policy>> TryBuild();
|
||||
sapi::StatusOr<std::unique_ptr<Policy>> TryBuild();
|
||||
|
||||
// Builds the policy returning a unique_ptr to it. This should only be called
|
||||
// once.
|
||||
|
@ -518,9 +518,9 @@ class PolicyBuilder final {
|
|||
|
||||
std::vector<sock_filter> ResolveBpfFunc(BpfFunc f);
|
||||
|
||||
static ::sapi::StatusOr<std::string> ValidateAbsolutePath(
|
||||
static sapi::StatusOr<std::string> ValidateAbsolutePath(
|
||||
absl::string_view path);
|
||||
static ::sapi::StatusOr<std::string> ValidatePath(absl::string_view path);
|
||||
static sapi::StatusOr<std::string> ValidatePath(absl::string_view path);
|
||||
|
||||
void StoreDescription(PolicyBuilderDescription* pb_description);
|
||||
|
||||
|
@ -540,10 +540,10 @@ class PolicyBuilder final {
|
|||
std::set<unsigned int> handled_syscalls_;
|
||||
|
||||
// Error handling
|
||||
::sapi::Status last_status_;
|
||||
sapi::Status last_status_;
|
||||
// This function returns a PolicyBuilder so that we can use it in the status
|
||||
// macros
|
||||
PolicyBuilder& SetError(const ::sapi::Status& status);
|
||||
PolicyBuilder& SetError(const sapi::Status& status);
|
||||
};
|
||||
|
||||
} // namespace sandbox2
|
||||
|
|
|
@ -57,7 +57,7 @@ class PolicyBuilderPeer {
|
|||
|
||||
int policy_size() const { return builder_->output_->user_policy_.size(); }
|
||||
|
||||
static ::sapi::StatusOr<std::string> ValidateAbsolutePath(
|
||||
static sapi::StatusOr<std::string> ValidateAbsolutePath(
|
||||
absl::string_view path) {
|
||||
return PolicyBuilder::ValidateAbsolutePath(path);
|
||||
}
|
||||
|
|
|
@ -29,47 +29,47 @@
|
|||
|
||||
namespace sandbox2 {
|
||||
|
||||
::sapi::Status Regs::Fetch() {
|
||||
sapi::Status Regs::Fetch() {
|
||||
#if defined(__powerpc64__)
|
||||
iovec pt_iov = {&user_regs_, sizeof(user_regs_)};
|
||||
|
||||
if (ptrace(PTRACE_GETREGSET, pid_, NT_PRSTATUS, &pt_iov) == -1L) {
|
||||
return ::sapi::InternalError(absl::StrCat(
|
||||
return sapi::InternalError(absl::StrCat(
|
||||
"ptrace(PTRACE_GETREGSET, pid=", pid_, ") failed: ", StrError(errno)));
|
||||
}
|
||||
if (pt_iov.iov_len != sizeof(user_regs_)) {
|
||||
return ::sapi::InternalError(absl::StrCat(
|
||||
return sapi::InternalError(absl::StrCat(
|
||||
"ptrace(PTRACE_GETREGSET, pid=", pid_,
|
||||
") size returned: ", pt_iov.iov_len,
|
||||
" different than sizeof(user_regs_): ", sizeof(user_regs_)));
|
||||
}
|
||||
#else
|
||||
if (ptrace(PTRACE_GETREGS, pid_, 0, &user_regs_) == -1L) {
|
||||
return ::sapi::InternalError(absl::StrCat(
|
||||
"ptrace(PTRACE_GETREGS, pid=", pid_, ") failed: ", StrError(errno)));
|
||||
return sapi::InternalError(absl::StrCat("ptrace(PTRACE_GETREGS, pid=", pid_,
|
||||
") failed: ", StrError(errno)));
|
||||
}
|
||||
#endif
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
::sapi::Status Regs::Store() {
|
||||
sapi::Status Regs::Store() {
|
||||
#if defined(__powerpc64__)
|
||||
iovec pt_iov = {&user_regs_, sizeof(user_regs_)};
|
||||
|
||||
if (ptrace(PTRACE_SETREGSET, pid_, NT_PRSTATUS, &pt_iov) == -1L) {
|
||||
return ::sapi::InternalError(absl::StrCat(
|
||||
return sapi::InternalError(absl::StrCat(
|
||||
"ptrace(PTRACE_SETREGSET, pid=", pid_, ") failed: ", StrError(errno)));
|
||||
}
|
||||
#else
|
||||
if (ptrace(PTRACE_SETREGS, pid_, 0, &user_regs_) == -1) {
|
||||
return ::sapi::InternalError(absl::StrCat(
|
||||
"ptrace(PTRACE_SETREGS, pid=", pid_, ") failed: ", StrError(errno)));
|
||||
return sapi::InternalError(absl::StrCat("ptrace(PTRACE_SETREGS, pid=", pid_,
|
||||
") failed: ", StrError(errno)));
|
||||
}
|
||||
#endif
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
::sapi::Status Regs::SkipSyscallReturnValue(uint64_t value) {
|
||||
sapi::Status Regs::SkipSyscallReturnValue(uint64_t value) {
|
||||
#if defined(__x86_64__)
|
||||
user_regs_.orig_rax = -1;
|
||||
user_regs_.rax = value;
|
||||
|
|
|
@ -40,13 +40,13 @@ class Regs {
|
|||
explicit Regs(pid_t pid) : pid_(pid) {}
|
||||
|
||||
// Copies register values from the process
|
||||
::sapi::Status Fetch();
|
||||
sapi::Status Fetch();
|
||||
|
||||
// Copies register values to the process
|
||||
::sapi::Status Store();
|
||||
sapi::Status Store();
|
||||
|
||||
// Causes the process to skip current syscall and return given value instead
|
||||
::sapi::Status SkipSyscallReturnValue(uint64_t value);
|
||||
sapi::Status SkipSyscallReturnValue(uint64_t value);
|
||||
|
||||
// Converts raw register values obtained on syscall entry to syscall info
|
||||
Syscall ToSyscall(Syscall::CpuArch syscall_arch) const;
|
||||
|
|
|
@ -43,19 +43,19 @@ Result& Result::operator=(const Result& other) {
|
|||
return *this;
|
||||
}
|
||||
|
||||
::sapi::Status Result::ToStatus() const {
|
||||
sapi::Status Result::ToStatus() const {
|
||||
switch (final_status()) {
|
||||
case OK:
|
||||
if (reason_code() == 0) {
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
break;
|
||||
case TIMEOUT:
|
||||
return ::sapi::DeadlineExceededError(ToString());
|
||||
return sapi::DeadlineExceededError(ToString());
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ::sapi::InternalError(ToString());
|
||||
return sapi::InternalError(ToString());
|
||||
}
|
||||
|
||||
std::string Result::ToString() const {
|
||||
|
|
|
@ -143,9 +143,9 @@ class Result {
|
|||
|
||||
void SetProcMaps(const std::string& proc_maps) { proc_maps_ = proc_maps; }
|
||||
|
||||
// Converts this result to a ::sapi::Status object. The status will only be
|
||||
// Converts this result to a sapi::Status object. The status will only be
|
||||
// OK if the sandbox process exited normally with an exit code of 0.
|
||||
::sapi::Status ToStatus() const;
|
||||
sapi::Status ToStatus() const;
|
||||
|
||||
// Returns a descriptive string for final result.
|
||||
std::string ToString() const;
|
||||
|
|
|
@ -41,8 +41,7 @@ sapi::StatusOr<Result> Sandbox2::AwaitResultWithTimeout(
|
|||
auto done =
|
||||
monitor_->done_notification_.WaitForNotificationWithTimeout(timeout);
|
||||
if (!done) {
|
||||
return ::sapi::DeadlineExceededError(
|
||||
"Sandbox did not finish within timeout");
|
||||
return sapi::DeadlineExceededError("Sandbox did not finish within timeout");
|
||||
}
|
||||
monitor_thread_->join();
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ class Sandbox2 final {
|
|||
// Waits for sandbox execution to finish within the timeout.
|
||||
// Returns execution result or a DeadlineExceededError if the sandboxee does
|
||||
// not finish in time.
|
||||
::sapi::StatusOr<Result> AwaitResultWithTimeout(absl::Duration timeout);
|
||||
sapi::StatusOr<Result> AwaitResultWithTimeout(absl::Duration timeout);
|
||||
|
||||
// Requests termination of the sandboxee.
|
||||
// Sandbox should still waited with AwaitResult(), as it may finish for other
|
||||
|
|
|
@ -180,15 +180,14 @@ bool CreateMemFd(int* fd, const char* name) {
|
|||
return true;
|
||||
}
|
||||
|
||||
::sapi::StatusOr<int> Communicate(const std::vector<std::string>& argv,
|
||||
sapi::StatusOr<int> Communicate(const std::vector<std::string>& argv,
|
||||
const std::vector<std::string>& envv,
|
||||
std::string* output) {
|
||||
int cout_pipe[2];
|
||||
posix_spawn_file_actions_t action;
|
||||
|
||||
if (pipe(cout_pipe) == -1) {
|
||||
return ::sapi::UnknownError(
|
||||
absl::StrCat("creating pipe: ", StrError(errno)));
|
||||
return sapi::UnknownError(absl::StrCat("creating pipe: ", StrError(errno)));
|
||||
}
|
||||
file_util::fileops::FDCloser cout_closer{cout_pipe[1]};
|
||||
|
||||
|
@ -217,7 +216,7 @@ bool CreateMemFd(int* fd, const char* name) {
|
|||
|
||||
pid_t pid;
|
||||
if (posix_spawnp(&pid, args[0], &action, nullptr, args, envp) != 0) {
|
||||
return ::sapi::UnknownError(
|
||||
return sapi::UnknownError(
|
||||
absl::StrCat("posix_spawnp() failed: ", StrError(errno)));
|
||||
}
|
||||
|
||||
|
@ -229,7 +228,7 @@ bool CreateMemFd(int* fd, const char* name) {
|
|||
int bytes_read =
|
||||
TEMP_FAILURE_RETRY(read(cout_pipe[0], &buffer[0], buffer.length()));
|
||||
if (bytes_read < 0) {
|
||||
return ::sapi::InternalError(
|
||||
return sapi::InternalError(
|
||||
absl::StrCat("reading from cout pipe failed: ", StrError(errno)));
|
||||
}
|
||||
if (bytes_read == 0) {
|
||||
|
@ -279,7 +278,7 @@ std::string GetRlimitName(int resource) {
|
|||
}
|
||||
}
|
||||
|
||||
::sapi::StatusOr<std::string> ReadCPathFromPid(pid_t pid, uintptr_t ptr) {
|
||||
sapi::StatusOr<std::string> ReadCPathFromPid(pid_t pid, uintptr_t ptr) {
|
||||
std::string path(PATH_MAX, '\0');
|
||||
iovec local_iov[] = {{&path[0], path.size()}};
|
||||
|
||||
|
@ -304,7 +303,7 @@ std::string GetRlimitName(int resource) {
|
|||
ssize_t sz = process_vm_readv(pid, local_iov, ABSL_ARRAYSIZE(local_iov),
|
||||
remote_iov, ABSL_ARRAYSIZE(remote_iov), 0);
|
||||
if (sz < 0) {
|
||||
return ::sapi::InternalError(absl::StrFormat(
|
||||
return sapi::InternalError(absl::StrFormat(
|
||||
"process_vm_readv() failed for PID: %d at address: %#x: %s", pid,
|
||||
reinterpret_cast<uintptr_t>(ptr), StrError(errno)));
|
||||
}
|
||||
|
@ -313,7 +312,7 @@ std::string GetRlimitName(int resource) {
|
|||
// incorrect path (or >PATH_MAX).
|
||||
auto pos = path.find('\0');
|
||||
if (pos == std::string::npos) {
|
||||
return ::sapi::FailedPreconditionError(absl::StrCat(
|
||||
return sapi::FailedPreconditionError(absl::StrCat(
|
||||
"No NUL-byte inside the C string '", absl::CHexEscape(path), "'"));
|
||||
}
|
||||
path.resize(pos);
|
||||
|
|
|
@ -62,7 +62,7 @@ bool CreateMemFd(int* fd, const char* name = "buffer_file");
|
|||
|
||||
// Executes a the program given by argv and the specified environment and
|
||||
// captures any output to stdout/stderr.
|
||||
::sapi::StatusOr<int> Communicate(const std::vector<std::string>& argv,
|
||||
sapi::StatusOr<int> Communicate(const std::vector<std::string>& argv,
|
||||
const std::vector<std::string>& envv,
|
||||
std::string* output);
|
||||
|
||||
|
@ -74,7 +74,7 @@ std::string GetRlimitName(int resource);
|
|||
|
||||
// Reads a path string (NUL-terminated, shorter than PATH_MAX) from another
|
||||
// process memory
|
||||
::sapi::StatusOr<std::string> ReadCPathFromPid(pid_t pid, uintptr_t ptr);
|
||||
sapi::StatusOr<std::string> ReadCPathFromPid(pid_t pid, uintptr_t ptr);
|
||||
|
||||
} // namespace util
|
||||
} // namespace sandbox2
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
namespace sandbox2 {
|
||||
|
||||
::sapi::StatusOr<std::vector<MapsEntry>> ParseProcMaps(
|
||||
sapi::StatusOr<std::vector<MapsEntry>> ParseProcMaps(
|
||||
const std::string& contents) {
|
||||
// Note: The format string
|
||||
// https://github.com/torvalds/linux/blob/v4.14/fs/proc/task_mmu.c#L289
|
||||
|
@ -45,7 +45,7 @@ namespace sandbox2 {
|
|||
} else if (n_matches == 11) {
|
||||
entry.path.resize(strlen(entry.path.c_str()));
|
||||
} else {
|
||||
return ::sapi::FailedPreconditionError("Invalid format");
|
||||
return sapi::FailedPreconditionError("Invalid format");
|
||||
}
|
||||
entry.is_readable = r == 'r';
|
||||
entry.is_writable = w == 'w';
|
||||
|
|
|
@ -38,7 +38,7 @@ struct MapsEntry {
|
|||
std::string path;
|
||||
};
|
||||
|
||||
::sapi::StatusOr<std::vector<MapsEntry>> ParseProcMaps(
|
||||
sapi::StatusOr<std::vector<MapsEntry>> ParseProcMaps(
|
||||
const std::string& contents);
|
||||
|
||||
} // namespace sandbox2
|
||||
|
|
|
@ -51,23 +51,23 @@ constexpr int kEvCurrent = 1; // ELF version
|
|||
namespace {
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
::sapi::Status CheckedFSeek(FILE* f, long offset, int whence) {
|
||||
sapi::Status CheckedFSeek(FILE* f, long offset, int whence) {
|
||||
if (fseek(f, offset, whence)) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
absl::StrCat("Fseek on ELF failed: ", StrError(errno)));
|
||||
}
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
::sapi::Status CheckedFRead(void* dst, size_t size, size_t nmemb, FILE* f) {
|
||||
sapi::Status CheckedFRead(void* dst, size_t size, size_t nmemb, FILE* f) {
|
||||
if (fread(dst, size, nmemb, f) == nmemb) {
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
absl::StrCat("Reading ELF data failed: ", StrError(errno)));
|
||||
}
|
||||
|
||||
::sapi::Status CheckedRead(std::string* s, FILE* f) {
|
||||
sapi::Status CheckedRead(std::string* s, FILE* f) {
|
||||
return CheckedFRead(&(*s)[0], 1, s->size(), f);
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,7 @@ class ElfParser {
|
|||
static constexpr size_t kMaxInterpreterSize = 1000;
|
||||
|
||||
ElfParser() = default;
|
||||
::sapi::StatusOr<ElfFile> Parse(FILE* elf, uint32_t features);
|
||||
sapi::StatusOr<ElfFile> Parse(FILE* elf, uint32_t features);
|
||||
|
||||
private:
|
||||
// Endianess support functions
|
||||
|
@ -130,25 +130,25 @@ class ElfParser {
|
|||
void Load(int64_t* dst, const void* src) { *dst = Load64(src); }
|
||||
|
||||
// Reads elf file size.
|
||||
::sapi::Status ReadFileSize();
|
||||
sapi::Status ReadFileSize();
|
||||
// Reads elf header.
|
||||
::sapi::Status ReadFileHeader();
|
||||
sapi::Status ReadFileHeader();
|
||||
// Reads a single elf program header.
|
||||
::sapi::StatusOr<Elf64_Phdr> ReadProgramHeader(absl::string_view src);
|
||||
sapi::StatusOr<Elf64_Phdr> ReadProgramHeader(absl::string_view src);
|
||||
// Reads all elf program headers.
|
||||
::sapi::Status ReadProgramHeaders();
|
||||
sapi::Status ReadProgramHeaders();
|
||||
// Reads a single elf section header.
|
||||
::sapi::StatusOr<Elf64_Shdr> ReadSectionHeader(absl::string_view src);
|
||||
sapi::StatusOr<Elf64_Shdr> ReadSectionHeader(absl::string_view src);
|
||||
// Reads all elf section headers.
|
||||
::sapi::Status ReadSectionHeaders();
|
||||
sapi::Status ReadSectionHeaders();
|
||||
// Reads contents of an elf section.
|
||||
::sapi::StatusOr<std::string> ReadSectionContents(int idx);
|
||||
::sapi::StatusOr<std::string> ReadSectionContents(
|
||||
sapi::StatusOr<std::string> ReadSectionContents(int idx);
|
||||
sapi::StatusOr<std::string> ReadSectionContents(
|
||||
const Elf64_Shdr& section_header);
|
||||
// Reads all symbols from symtab section.
|
||||
::sapi::Status ReadSymbolsFromSymtab(const Elf64_Shdr& symtab);
|
||||
sapi::Status ReadSymbolsFromSymtab(const Elf64_Shdr& symtab);
|
||||
// Reads all imported libraries from dynamic section.
|
||||
::sapi::Status ReadImportedLibrariesFromDynamic(const Elf64_Shdr& dynamic);
|
||||
sapi::Status ReadImportedLibrariesFromDynamic(const Elf64_Shdr& dynamic);
|
||||
|
||||
ElfFile result_;
|
||||
FILE* elf_ = nullptr;
|
||||
|
@ -171,37 +171,37 @@ constexpr int ElfParser::kMaxSymbolEntries;
|
|||
constexpr int ElfParser::kMaxDynamicEntries;
|
||||
constexpr size_t ElfParser::kMaxInterpreterSize;
|
||||
|
||||
::sapi::Status ElfParser::ReadFileSize() {
|
||||
sapi::Status ElfParser::ReadFileSize() {
|
||||
fseek(elf_, 0, SEEK_END);
|
||||
file_size_ = ftell(elf_);
|
||||
if (file_size_ < kElfHeaderSize) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
absl::StrCat("file too small: ", file_size_, " bytes, at least ",
|
||||
kElfHeaderSize, " bytes expected"));
|
||||
}
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
::sapi::Status ElfParser::ReadFileHeader() {
|
||||
sapi::Status ElfParser::ReadFileHeader() {
|
||||
std::string header(kElfHeaderSize, '\0');
|
||||
SAPI_RETURN_IF_ERROR(CheckedFSeek(elf_, 0, SEEK_SET));
|
||||
SAPI_RETURN_IF_ERROR(CheckedRead(&header, elf_));
|
||||
|
||||
if (!absl::StartsWith(header, kElfMagic)) {
|
||||
return ::sapi::FailedPreconditionError("magic not found, not an ELF");
|
||||
return sapi::FailedPreconditionError("magic not found, not an ELF");
|
||||
}
|
||||
|
||||
if (header[kEiClassOffset] != kEiClass64) {
|
||||
return ::sapi::FailedPreconditionError("invalid ELF class");
|
||||
return sapi::FailedPreconditionError("invalid ELF class");
|
||||
}
|
||||
const auto elf_data = header[kEiDataOffset];
|
||||
elf_little_ = elf_data == kEiDataLittle;
|
||||
if (!elf_little_ && elf_data != kEiDataBig) {
|
||||
return ::sapi::FailedPreconditionError("invalid endianness");
|
||||
return sapi::FailedPreconditionError("invalid endianness");
|
||||
}
|
||||
|
||||
if (header[kEiVersionOffset] != kEvCurrent) {
|
||||
return ::sapi::FailedPreconditionError("invalid ELF version");
|
||||
return sapi::FailedPreconditionError("invalid ELF version");
|
||||
}
|
||||
LOAD_MEMBER(file_header_, e_ident, header.data());
|
||||
LOAD_MEMBER(file_header_, e_type, header.data());
|
||||
|
@ -217,13 +217,13 @@ constexpr size_t ElfParser::kMaxInterpreterSize;
|
|||
LOAD_MEMBER(file_header_, e_shentsize, header.data());
|
||||
LOAD_MEMBER(file_header_, e_shnum, header.data());
|
||||
LOAD_MEMBER(file_header_, e_shstrndx, header.data());
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
::sapi::StatusOr<Elf64_Shdr> ElfParser::ReadSectionHeader(
|
||||
sapi::StatusOr<Elf64_Shdr> ElfParser::ReadSectionHeader(
|
||||
absl::string_view src) {
|
||||
if (src.size() < sizeof(Elf64_Shdr)) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
absl::StrCat("invalid section header data: got ", src.size(),
|
||||
" bytes, ", sizeof(Elf64_Shdr), " bytes expected."));
|
||||
}
|
||||
|
@ -241,18 +241,18 @@ constexpr size_t ElfParser::kMaxInterpreterSize;
|
|||
return rv;
|
||||
}
|
||||
|
||||
::sapi::Status ElfParser::ReadSectionHeaders() {
|
||||
sapi::Status ElfParser::ReadSectionHeaders() {
|
||||
if (file_header_.e_shoff > file_size_) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
absl::StrCat("invalid section header offset: ", file_header_.e_shoff));
|
||||
}
|
||||
if (file_header_.e_shentsize != sizeof(Elf64_Shdr)) {
|
||||
return ::sapi::FailedPreconditionError(absl::StrCat(
|
||||
return sapi::FailedPreconditionError(absl::StrCat(
|
||||
"section header entry size incorrect: ", file_header_.e_shentsize,
|
||||
" bytes, ", sizeof(Elf64_Shdr), " expected."));
|
||||
}
|
||||
if (file_header_.e_shnum > kMaxSectionHeaderEntries) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
absl::StrCat("too many section header entries: ", file_header_.e_shnum,
|
||||
" limit: ", kMaxSectionHeaderEntries));
|
||||
}
|
||||
|
@ -265,27 +265,27 @@ constexpr size_t ElfParser::kMaxInterpreterSize;
|
|||
SAPI_ASSIGN_OR_RETURN(section_headers_[i], ReadSectionHeader(src));
|
||||
src = src.substr(file_header_.e_shentsize);
|
||||
}
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
::sapi::StatusOr<std::string> ElfParser::ReadSectionContents(int idx) {
|
||||
sapi::StatusOr<std::string> ElfParser::ReadSectionContents(int idx) {
|
||||
if (idx < 0 || idx >= section_headers_.size()) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
absl::StrCat("invalid section header index: ", idx));
|
||||
}
|
||||
return ReadSectionContents(section_headers_.at(idx));
|
||||
}
|
||||
|
||||
::sapi::StatusOr<std::string> ElfParser::ReadSectionContents(
|
||||
sapi::StatusOr<std::string> ElfParser::ReadSectionContents(
|
||||
const Elf64_Shdr& section_header) {
|
||||
auto offset = section_header.sh_offset;
|
||||
if (offset > file_size_) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
absl::StrCat("invalid section offset: ", offset));
|
||||
}
|
||||
auto size = section_header.sh_size;
|
||||
if (size > kMaxSectionSize) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
absl::StrCat("section too big: ", size, " limit: ", kMaxSectionSize));
|
||||
}
|
||||
std::string rv(size, '\0');
|
||||
|
@ -294,10 +294,10 @@ constexpr size_t ElfParser::kMaxInterpreterSize;
|
|||
return rv;
|
||||
}
|
||||
|
||||
::sapi::StatusOr<Elf64_Phdr> ElfParser::ReadProgramHeader(
|
||||
sapi::StatusOr<Elf64_Phdr> ElfParser::ReadProgramHeader(
|
||||
absl::string_view src) {
|
||||
if (src.size() < sizeof(Elf64_Phdr)) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
absl::StrCat("invalid program header data: got ", src.size(),
|
||||
" bytes, ", sizeof(Elf64_Phdr), " bytes expected."));
|
||||
}
|
||||
|
@ -313,18 +313,18 @@ constexpr size_t ElfParser::kMaxInterpreterSize;
|
|||
return rv;
|
||||
}
|
||||
|
||||
::sapi::Status ElfParser::ReadProgramHeaders() {
|
||||
sapi::Status ElfParser::ReadProgramHeaders() {
|
||||
if (file_header_.e_phoff > file_size_) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
absl::StrCat("invalid program header offset: ", file_header_.e_phoff));
|
||||
}
|
||||
if (file_header_.e_phentsize != sizeof(Elf64_Phdr)) {
|
||||
return ::sapi::FailedPreconditionError(absl::StrCat(
|
||||
return sapi::FailedPreconditionError(absl::StrCat(
|
||||
"section header entry size incorrect: ", file_header_.e_phentsize,
|
||||
" bytes, ", sizeof(Elf64_Phdr), " expected."));
|
||||
}
|
||||
if (file_header_.e_phnum > kMaxProgramHeaderEntries) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
absl::StrCat("too many program header entries: ", file_header_.e_phnum,
|
||||
" limit: ", kMaxProgramHeaderEntries));
|
||||
}
|
||||
|
@ -337,29 +337,29 @@ constexpr size_t ElfParser::kMaxInterpreterSize;
|
|||
SAPI_ASSIGN_OR_RETURN(program_headers_[i], ReadProgramHeader(src));
|
||||
src = src.substr(file_header_.e_phentsize);
|
||||
}
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
::sapi::Status ElfParser::ReadSymbolsFromSymtab(const Elf64_Shdr& symtab) {
|
||||
sapi::Status ElfParser::ReadSymbolsFromSymtab(const Elf64_Shdr& symtab) {
|
||||
if (symtab.sh_type != SHT_SYMTAB) {
|
||||
return ::sapi::FailedPreconditionError("invalid symtab type");
|
||||
return sapi::FailedPreconditionError("invalid symtab type");
|
||||
}
|
||||
if (symtab.sh_entsize != sizeof(Elf64_Sym)) {
|
||||
return ::sapi::InternalError(
|
||||
return sapi::InternalError(
|
||||
absl::StrCat("invalid symbol entry size: ", symtab.sh_entsize));
|
||||
}
|
||||
if ((symtab.sh_size % symtab.sh_entsize) != 0) {
|
||||
return ::sapi::InternalError(
|
||||
return sapi::InternalError(
|
||||
absl::StrCat("invalid symbol table size: ", symtab.sh_size));
|
||||
}
|
||||
size_t symbol_entries = symtab.sh_size / symtab.sh_entsize;
|
||||
if (symbol_entries > kMaxSymbolEntries - symbol_entries_read) {
|
||||
return ::sapi::InternalError(
|
||||
return sapi::InternalError(
|
||||
absl::StrCat("too many symbols: ", symbol_entries));
|
||||
}
|
||||
symbol_entries_read += symbol_entries;
|
||||
if (symtab.sh_link >= section_headers_.size()) {
|
||||
return ::sapi::InternalError(
|
||||
return sapi::InternalError(
|
||||
absl::StrCat("invalid symtab's strtab reference: ", symtab.sh_link));
|
||||
}
|
||||
SAPI_RAW_VLOG(1, "Symbol table with %d entries found", symbol_entries);
|
||||
|
@ -384,53 +384,53 @@ constexpr size_t ElfParser::kMaxInterpreterSize;
|
|||
continue;
|
||||
}
|
||||
if (symbol.st_shndx >= section_headers_.size()) {
|
||||
return ::sapi::FailedPreconditionError(absl::StrCat(
|
||||
return sapi::FailedPreconditionError(absl::StrCat(
|
||||
"invalid symbol data: section index: ", symbol.st_shndx));
|
||||
}
|
||||
if (symbol.st_name >= strtab.size()) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
absl::StrCat("invalid name reference: REL", symbol.st_value));
|
||||
}
|
||||
result_.symbols_.push_back(
|
||||
{symbol.st_value, std::string(ReadName(symbol.st_name, strtab))});
|
||||
}
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
::sapi::Status ElfParser::ReadImportedLibrariesFromDynamic(
|
||||
sapi::Status ElfParser::ReadImportedLibrariesFromDynamic(
|
||||
const Elf64_Shdr& dynamic) {
|
||||
if (dynamic.sh_type != SHT_DYNAMIC) {
|
||||
return ::sapi::FailedPreconditionError("invalid dynamic type");
|
||||
return sapi::FailedPreconditionError("invalid dynamic type");
|
||||
}
|
||||
if (dynamic.sh_entsize != sizeof(Elf64_Dyn)) {
|
||||
return ::sapi::InternalError(
|
||||
return sapi::InternalError(
|
||||
absl::StrCat("invalid dynamic entry size: ", dynamic.sh_entsize));
|
||||
}
|
||||
if ((dynamic.sh_size % dynamic.sh_entsize) != 0) {
|
||||
return ::sapi::InternalError(
|
||||
return sapi::InternalError(
|
||||
absl::StrCat("invalid dynamic table size: ", dynamic.sh_size));
|
||||
}
|
||||
size_t entries = dynamic.sh_size / dynamic.sh_entsize;
|
||||
if (entries > kMaxDynamicEntries - dynamic_entries_read) {
|
||||
return ::sapi::InternalError(
|
||||
return sapi::InternalError(
|
||||
absl::StrCat("too many dynamic entries: ", entries));
|
||||
}
|
||||
dynamic_entries_read += entries;
|
||||
if (dynamic.sh_link >= section_headers_.size()) {
|
||||
return ::sapi::InternalError(
|
||||
return sapi::InternalError(
|
||||
absl::StrCat("invalid dynamic's strtab reference: ", dynamic.sh_link));
|
||||
}
|
||||
SAPI_RAW_VLOG(1, "Dynamic section with %d entries found", entries);
|
||||
// strtab may be shared with symbols and therefore huge
|
||||
const auto& strtab_section = section_headers_.at(dynamic.sh_link);
|
||||
if (strtab_section.sh_offset > file_size_) {
|
||||
return ::sapi::FailedPreconditionError(absl::StrCat(
|
||||
return sapi::FailedPreconditionError(absl::StrCat(
|
||||
"invalid symtab's strtab section offset: ", strtab_section.sh_offset));
|
||||
}
|
||||
if (strtab_section.sh_size >= kMaxStrtabSize ||
|
||||
strtab_section.sh_size >= file_size_ ||
|
||||
strtab_section.sh_offset >= file_size_ - strtab_section.sh_size) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
absl::StrCat("symtab's strtab too big: ", strtab_section.sh_size));
|
||||
}
|
||||
auto strtab_end = strtab_section.sh_offset + strtab_section.sh_size;
|
||||
|
@ -444,7 +444,7 @@ constexpr size_t ElfParser::kMaxInterpreterSize;
|
|||
continue;
|
||||
}
|
||||
if (dyn.d_un.d_val >= strtab_section.sh_size) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
absl::StrCat("invalid name reference"));
|
||||
}
|
||||
auto offset = strtab_section.sh_offset + dyn.d_un.d_val;
|
||||
|
@ -454,14 +454,14 @@ constexpr size_t ElfParser::kMaxInterpreterSize;
|
|||
path.resize(size);
|
||||
result_.imported_libraries_.push_back(path.substr(0, path.find('\0')));
|
||||
}
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
::sapi::StatusOr<ElfFile> ElfParser::Parse(FILE* elf, uint32_t features) {
|
||||
sapi::StatusOr<ElfFile> ElfParser::Parse(FILE* elf, uint32_t features) {
|
||||
elf_ = elf;
|
||||
// Basic sanity check.
|
||||
if (features & ~(ElfFile::kAll)) {
|
||||
return ::sapi::InvalidArgumentError("Unknown feature flags specified");
|
||||
return sapi::InvalidArgumentError("Unknown feature flags specified");
|
||||
}
|
||||
SAPI_RETURN_IF_ERROR(ReadFileSize());
|
||||
SAPI_RETURN_IF_ERROR(ReadFileHeader());
|
||||
|
@ -473,7 +473,7 @@ constexpr size_t ElfParser::kMaxInterpreterSize;
|
|||
result_.position_independent_ = true;
|
||||
break;
|
||||
default:
|
||||
return ::sapi::FailedPreconditionError("not an executable: ");
|
||||
return sapi::FailedPreconditionError("not an executable: ");
|
||||
}
|
||||
if (features & ElfFile::kGetInterpreter) {
|
||||
SAPI_RETURN_IF_ERROR(ReadProgramHeaders());
|
||||
|
@ -484,7 +484,7 @@ constexpr size_t ElfParser::kMaxInterpreterSize;
|
|||
// No interpreter usually means that the executable was statically linked.
|
||||
if (it != program_headers_.end()) {
|
||||
if (it->p_filesz > kMaxInterpreterSize) {
|
||||
return ::sapi::FailedPreconditionError(
|
||||
return sapi::FailedPreconditionError(
|
||||
absl::StrCat("program interpeter path too long: ", it->p_filesz));
|
||||
}
|
||||
SAPI_RETURN_IF_ERROR(CheckedFSeek(elf, it->p_offset, SEEK_SET));
|
||||
|
@ -514,12 +514,12 @@ constexpr size_t ElfParser::kMaxInterpreterSize;
|
|||
return std::move(result_);
|
||||
}
|
||||
|
||||
::sapi::StatusOr<ElfFile> ElfFile::ParseFromFile(const std::string& filename,
|
||||
sapi::StatusOr<ElfFile> ElfFile::ParseFromFile(const std::string& filename,
|
||||
uint32_t features) {
|
||||
std::unique_ptr<FILE, void (*)(FILE*)> elf{fopen(filename.c_str(), "r"),
|
||||
[](FILE* f) { fclose(f); }};
|
||||
if (!elf) {
|
||||
return ::sapi::UnknownError(
|
||||
return sapi::UnknownError(
|
||||
absl::StrCat("cannot open file: ", filename, ": ", StrError(errno)));
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ class ElfFile {
|
|||
std::string name;
|
||||
};
|
||||
|
||||
static ::sapi::StatusOr<ElfFile> ParseFromFile(const std::string& filename,
|
||||
static sapi::StatusOr<ElfFile> ParseFromFile(const std::string& filename,
|
||||
uint32_t features);
|
||||
|
||||
int64_t file_size() const { return file_size_; }
|
||||
|
|
|
@ -33,17 +33,17 @@ namespace {
|
|||
constexpr absl::string_view kMktempSuffix = "XXXXXX";
|
||||
} // namespace
|
||||
|
||||
::sapi::StatusOr<std::pair<std::string, int>> CreateNamedTempFile(
|
||||
sapi::StatusOr<std::pair<std::string, int>> CreateNamedTempFile(
|
||||
absl::string_view prefix) {
|
||||
std::string name_template = absl::StrCat(prefix, kMktempSuffix);
|
||||
int fd = mkstemp(&name_template[0]);
|
||||
if (fd < 0) {
|
||||
return ::sapi::UnknownError(absl::StrCat("mkstemp():", StrError(errno)));
|
||||
return sapi::UnknownError(absl::StrCat("mkstemp():", StrError(errno)));
|
||||
}
|
||||
return std::pair<std::string, int>{std::move(name_template), fd};
|
||||
}
|
||||
|
||||
::sapi::StatusOr<std::string> CreateNamedTempFileAndClose(
|
||||
sapi::StatusOr<std::string> CreateNamedTempFileAndClose(
|
||||
absl::string_view prefix) {
|
||||
auto result_or = CreateNamedTempFile(prefix);
|
||||
if (result_or.ok()) {
|
||||
|
@ -56,10 +56,10 @@ constexpr absl::string_view kMktempSuffix = "XXXXXX";
|
|||
return result_or.status();
|
||||
}
|
||||
|
||||
::sapi::StatusOr<std::string> CreateTempDir(absl::string_view prefix) {
|
||||
sapi::StatusOr<std::string> CreateTempDir(absl::string_view prefix) {
|
||||
std::string name_template = absl::StrCat(prefix, kMktempSuffix);
|
||||
if (mkdtemp(&name_template[0]) == nullptr) {
|
||||
return ::sapi::UnknownError(absl::StrCat("mkdtemp():", StrError(errno)));
|
||||
return sapi::UnknownError(absl::StrCat("mkdtemp():", StrError(errno)));
|
||||
}
|
||||
return name_template;
|
||||
}
|
||||
|
|
|
@ -23,18 +23,18 @@ namespace sandbox2 {
|
|||
|
||||
// Creates a temporary file under a path starting with prefix. File is not
|
||||
// unlinked and its path is returned together with an open fd.
|
||||
::sapi::StatusOr<std::pair<std::string, int>> CreateNamedTempFile(
|
||||
sapi::StatusOr<std::pair<std::string, int>> CreateNamedTempFile(
|
||||
absl::string_view prefix);
|
||||
|
||||
// Creates a temporary file under a path starting with prefix. File is not
|
||||
// unlinked and its path is returned. FD of the created file is closed just
|
||||
// after creation.
|
||||
::sapi::StatusOr<std::string> CreateNamedTempFileAndClose(
|
||||
sapi::StatusOr<std::string> CreateNamedTempFileAndClose(
|
||||
absl::string_view prefix);
|
||||
|
||||
// Creates a temporary directory under a path starting with prefix.
|
||||
// Returns the path of the created directory.
|
||||
::sapi::StatusOr<std::string> CreateTempDir(absl::string_view prefix);
|
||||
sapi::StatusOr<std::string> CreateTempDir(absl::string_view prefix);
|
||||
|
||||
} // namespace sandbox2
|
||||
|
||||
|
|
|
@ -457,8 +457,8 @@ class ReturnType(ArgumentType):
|
|||
"""Class representing function return type.
|
||||
|
||||
Attributes:
|
||||
return_type: ::sapi::StatusOr<T> where T is original return type, or
|
||||
::sapi::Status for functions returning void
|
||||
return_type: sapi::StatusOr<T> where T is original return type, or
|
||||
sapi::Status for functions returning void
|
||||
"""
|
||||
|
||||
def __init__(self, function, arg_type):
|
||||
|
@ -470,8 +470,8 @@ class ReturnType(ArgumentType):
|
|||
"""Returns function return type prepared from the type."""
|
||||
# TODO(szwl): const ptrs do not play well with SAPI C++ API...
|
||||
spelling = self._clang_type.spelling.replace('const', '')
|
||||
return_type = '::sapi::StatusOr<{}>'.format(spelling)
|
||||
return_type = '::sapi::Status' if self.is_void() else return_type
|
||||
return_type = 'sapi::StatusOr<{}>'.format(spelling)
|
||||
return_type = 'sapi::Status' if self.is_void() else return_type
|
||||
return return_type
|
||||
|
||||
|
||||
|
@ -832,7 +832,7 @@ class Generator(object):
|
|||
result.append(' SAPI_RETURN_IF_ERROR(sandbox_->Call("{}", &ret{}));'
|
||||
''.format(f.name, ', '.join(call_arguments)))
|
||||
|
||||
return_status = 'return ::sapi::OkStatus();'
|
||||
return_status = 'return sapi::OkStatus();'
|
||||
if f.result and not f.result.is_void():
|
||||
if f.result and f.result.is_enum():
|
||||
return_status = ('return static_cast<{}>'
|
||||
|
|
|
@ -32,7 +32,7 @@ class TestApi {
|
|||
::sapi::Sandbox* sandbox() const { return sandbox_; }
|
||||
|
||||
// int function_a(int, int)
|
||||
::sapi::StatusOr<int> function_a(int x, int y) {
|
||||
sapi::StatusOr<int> function_a(int x, int y) {
|
||||
::sapi::v::Int ret;
|
||||
::sapi::v::Int x_((x));
|
||||
::sapi::v::Int y_((y));
|
||||
|
@ -42,7 +42,7 @@ class TestApi {
|
|||
}
|
||||
|
||||
// int types_1(bool, unsigned char, char, unsigned short, short)
|
||||
::sapi::StatusOr<int> types_1(bool a0, unsigned char a1, char a2, unsigned short a3, short a4) {
|
||||
sapi::StatusOr<int> types_1(bool a0, unsigned char a1, char a2, unsigned short a3, short a4) {
|
||||
::sapi::v::Int ret;
|
||||
::sapi::v::Bool a0_((a0));
|
||||
::sapi::v::UChar a1_((a1));
|
||||
|
@ -55,7 +55,7 @@ class TestApi {
|
|||
}
|
||||
|
||||
// int types_2(int, unsigned int, long, unsigned long)
|
||||
::sapi::StatusOr<int> types_2(int a0, unsigned int a1, long a2, unsigned long a3) {
|
||||
sapi::StatusOr<int> types_2(int a0, unsigned int a1, long a2, unsigned long a3) {
|
||||
::sapi::v::Int ret;
|
||||
::sapi::v::Int a0_((a0));
|
||||
::sapi::v::UInt a1_((a1));
|
||||
|
@ -67,7 +67,7 @@ class TestApi {
|
|||
}
|
||||
|
||||
// int types_3(long long, unsigned long long, float, double)
|
||||
::sapi::StatusOr<int> types_3(long long a0, unsigned long long a1, float a2, double a3) {
|
||||
sapi::StatusOr<int> types_3(long long a0, unsigned long long a1, float a2, double a3) {
|
||||
::sapi::v::Int ret;
|
||||
::sapi::v::LLong a0_((a0));
|
||||
::sapi::v::ULLong a1_((a1));
|
||||
|
@ -79,7 +79,7 @@ class TestApi {
|
|||
}
|
||||
|
||||
// int types_4(signed char, short, int, long)
|
||||
::sapi::StatusOr<int> types_4(signed char a0, short a1, int a2, long a3) {
|
||||
sapi::StatusOr<int> types_4(signed char a0, short a1, int a2, long a3) {
|
||||
::sapi::v::Int ret;
|
||||
::sapi::v::SChar a0_((a0));
|
||||
::sapi::v::Short a1_((a1));
|
||||
|
@ -91,7 +91,7 @@ class TestApi {
|
|||
}
|
||||
|
||||
// int types_5(long long, long double)
|
||||
::sapi::StatusOr<int> types_5(long long a0, long double a1) {
|
||||
sapi::StatusOr<int> types_5(long long a0, long double a1) {
|
||||
::sapi::v::Int ret;
|
||||
::sapi::v::LLong a0_((a0));
|
||||
::sapi::v::Reg<long double> a1_((a1));
|
||||
|
@ -101,11 +101,11 @@ class TestApi {
|
|||
}
|
||||
|
||||
// void types_6(char *)
|
||||
::sapi::Status types_6(::sapi::v::Ptr* a0) {
|
||||
sapi::Status types_6(::sapi::v::Ptr* a0) {
|
||||
::sapi::v::Void ret;
|
||||
|
||||
SAPI_RETURN_IF_ERROR(sandbox_->Call("types_6", &ret, a0));
|
||||
return ::sapi::OkStatus();
|
||||
return sapi::OkStatus();
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -136,7 +136,7 @@ class TestApi {
|
|||
::sapi::Sandbox* sandbox() const { return sandbox_; }
|
||||
|
||||
// uint function(uintp)
|
||||
::sapi::StatusOr<uint> function(::sapi::v::Ptr* a) {
|
||||
sapi::StatusOr<uint> function(::sapi::v::Ptr* a) {
|
||||
::sapi::v::UInt ret;
|
||||
|
||||
SAPI_RETURN_IF_ERROR(sandbox_->Call("function", &ret, a));
|
||||
|
@ -173,7 +173,7 @@ class TestApi {
|
|||
::sapi::Sandbox* sandbox() const { return sandbox_; }
|
||||
|
||||
// ProcessStatus ProcessDatapoint(ProcessStatus)
|
||||
::sapi::StatusOr<ProcessStatus> ProcessDatapoint(ProcessStatus status) {
|
||||
sapi::StatusOr<ProcessStatus> ProcessDatapoint(ProcessStatus status) {
|
||||
::sapi::v::IntBase<ProcessStatus> ret;
|
||||
::sapi::v::IntBase<ProcessStatus> status_((status));
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user