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 #include "sandboxed_api/rpcchannel.h"
16
17 #include <cstdint>
18 #include <cstring>
19
20 #include "absl/log/log.h"
21 #include "absl/status/status.h"
22 #include "absl/status/statusor.h"
23 #include "absl/strings/str_cat.h"
24 #include "absl/synchronization/mutex.h"
25 #include "sandboxed_api/call.h"
26 #include "sandboxed_api/sandbox2/comms.h"
27 #include "sandboxed_api/util/status_macros.h"
28
29 namespace sapi {
30
Call(const FuncCall & call,uint32_t tag,FuncRet * ret,v::Type exp_type)31 absl::Status RPCChannel::Call(const FuncCall& call, uint32_t tag, FuncRet* ret,
32 v::Type exp_type) {
33 absl::MutexLock lock(&mutex_);
34 if (!comms_->SendTLV(tag, sizeof(call), &call)) {
35 return absl::UnavailableError("Sending TLV value failed");
36 }
37 SAPI_ASSIGN_OR_RETURN(auto fret, Return(exp_type));
38 *ret = fret;
39 return absl::OkStatus();
40 }
41
Return(v::Type exp_type)42 absl::StatusOr<FuncRet> RPCChannel::Return(v::Type exp_type) {
43 uint32_t tag;
44 size_t len;
45 FuncRet ret;
46 if (!comms_->RecvTLV(&tag, &len, &ret, sizeof(ret), comms::kMsgReturn)) {
47 return absl::UnavailableError("Receiving TLV value failed");
48 }
49 if (len != sizeof(FuncRet)) {
50 LOG(ERROR) << "len != sizeof(FuncReturn) (" << len
51 << " != " << sizeof(FuncRet) << ")";
52 return absl::UnavailableError("Received TLV has incorrect length");
53 }
54 if (ret.ret_type != exp_type) {
55 LOG(ERROR) << "FuncRet->type != exp_type (" << ret.ret_type
56 << " != " << exp_type << ")";
57 return absl::UnavailableError("Received TLV has incorrect return type");
58 }
59 if (!ret.success) {
60 LOG(ERROR) << "FuncRet->success == false";
61 return absl::UnavailableError("Function call failed");
62 }
63 return ret;
64 }
65
Allocate(size_t size,void ** addr)66 absl::Status RPCChannel::Allocate(size_t size, void** addr) {
67 absl::MutexLock lock(&mutex_);
68 if (!comms_->SendTLV(comms::kMsgAllocate, sizeof(size), &size)) {
69 return absl::UnavailableError("Sending TLV value failed");
70 }
71
72 SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kPointer));
73 *addr = reinterpret_cast<void*>(fret.int_val);
74 return absl::OkStatus();
75 }
76
Reallocate(void * old_addr,size_t size,void ** new_addr)77 absl::Status RPCChannel::Reallocate(void* old_addr, size_t size,
78 void** new_addr) {
79 absl::MutexLock lock(&mutex_);
80 comms::ReallocRequest req = {
81 .old_addr = reinterpret_cast<uintptr_t>(old_addr),
82 .size = size,
83 };
84
85 if (!comms_->SendTLV(comms::kMsgReallocate, sizeof(comms::ReallocRequest),
86 &req)) {
87 return absl::UnavailableError("Sending TLV value failed");
88 }
89
90 auto fret_or = Return(v::Type::kPointer);
91 if (!fret_or.ok()) {
92 *new_addr = nullptr;
93 return absl::UnavailableError(
94 absl::StrCat("Reallocate() failed on the remote side: ",
95 fret_or.status().message()));
96 }
97 *new_addr = reinterpret_cast<void*>(fret_or->int_val);
98 return absl::OkStatus();
99 }
100
Free(void * addr)101 absl::Status RPCChannel::Free(void* addr) {
102 absl::MutexLock lock(&mutex_);
103 uintptr_t remote = reinterpret_cast<uintptr_t>(addr);
104 if (!comms_->SendTLV(comms::kMsgFree, sizeof(remote), &remote)) {
105 return absl::UnavailableError("Sending TLV value failed");
106 }
107
108 SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kVoid));
109 if (!fret.success) {
110 return absl::UnavailableError("Free() failed on the remote side");
111 }
112 return absl::OkStatus();
113 }
114
Symbol(const char * symname,void ** addr)115 absl::Status RPCChannel::Symbol(const char* symname, void** addr) {
116 absl::MutexLock lock(&mutex_);
117 if (!comms_->SendTLV(comms::kMsgSymbol, strlen(symname) + 1, symname)) {
118 return absl::UnavailableError("Sending TLV value failed");
119 }
120
121 SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kPointer));
122 *addr = reinterpret_cast<void*>(fret.int_val);
123 return absl::OkStatus();
124 }
125
Exit()126 absl::Status RPCChannel::Exit() {
127 absl::MutexLock lock(&mutex_);
128 if (comms_->IsTerminated()) {
129 VLOG(2) << "Comms channel already terminated";
130 return absl::OkStatus();
131 }
132
133 // Try the RPC exit sequence. But, the only thing that matters as a success
134 // indicator is whether the Comms channel had been closed
135 comms_->SendTLV(comms::kMsgExit, 0, nullptr);
136 return absl::OkStatus();
137 }
138
SendFD(int local_fd,int * remote_fd)139 absl::Status RPCChannel::SendFD(int local_fd, int* remote_fd) {
140 absl::MutexLock lock(&mutex_);
141 if (!comms_->SendTLV(comms::kMsgSendFd, 0, nullptr)) {
142 return absl::UnavailableError("Sending TLV value failed");
143 }
144 if (!comms_->SendFD(local_fd)) {
145 return absl::UnavailableError("Sending FD failed");
146 }
147
148 SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kInt));
149 if (!fret.success) {
150 return absl::UnavailableError("SendFD failed on the remote side");
151 }
152 *remote_fd = fret.int_val;
153 return absl::OkStatus();
154 }
155
RecvFD(int remote_fd,int * local_fd)156 absl::Status RPCChannel::RecvFD(int remote_fd, int* local_fd) {
157 absl::MutexLock lock(&mutex_);
158 if (!comms_->SendTLV(comms::kMsgRecvFd, sizeof(remote_fd), &remote_fd)) {
159 return absl::UnavailableError("Sending TLV value failed");
160 }
161
162 if (!comms_->RecvFD(local_fd)) {
163 return absl::UnavailableError("Receving FD failed");
164 }
165
166 SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kVoid));
167 if (!fret.success) {
168 return absl::UnavailableError("RecvFD failed on the remote side");
169 }
170 return absl::OkStatus();
171 }
172
Close(int remote_fd)173 absl::Status RPCChannel::Close(int remote_fd) {
174 absl::MutexLock lock(&mutex_);
175 if (!comms_->SendTLV(comms::kMsgClose, sizeof(remote_fd), &remote_fd)) {
176 return absl::UnavailableError("Sending TLV value failed");
177 }
178
179 SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kVoid));
180 if (!fret.success) {
181 return absl::UnavailableError("Close() failed on the remote side");
182 }
183 return absl::OkStatus();
184 }
185
Strlen(void * str)186 absl::StatusOr<size_t> RPCChannel::Strlen(void* str) {
187 absl::MutexLock lock(&mutex_);
188 if (!comms_->SendTLV(comms::kMsgStrlen, sizeof(str), &str)) {
189 return absl::UnavailableError("Sending TLV value failed");
190 }
191
192 SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kInt));
193 if (!fret.success) {
194 return absl::UnavailableError("Close() failed on the remote side");
195 }
196 return fret.int_val;
197 }
198
199 } // namespace sapi
200