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