• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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