xref: /aosp_15_r20/external/sandboxed-api/sandboxed_api/client.cc (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
1*ec63e07aSXin Li // Copyright 2019 Google LLC
2*ec63e07aSXin Li //
3*ec63e07aSXin Li // Licensed under the Apache License, Version 2.0 (the "License");
4*ec63e07aSXin Li // you may not use this file except in compliance with the License.
5*ec63e07aSXin Li // You may obtain a copy of the License at
6*ec63e07aSXin Li //
7*ec63e07aSXin Li //     https://www.apache.org/licenses/LICENSE-2.0
8*ec63e07aSXin Li //
9*ec63e07aSXin Li // Unless required by applicable law or agreed to in writing, software
10*ec63e07aSXin Li // distributed under the License is distributed on an "AS IS" BASIS,
11*ec63e07aSXin Li // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*ec63e07aSXin Li // See the License for the specific language governing permissions and
13*ec63e07aSXin Li // limitations under the License.
14*ec63e07aSXin Li 
15*ec63e07aSXin Li #include <dlfcn.h>
16*ec63e07aSXin Li #include <syscall.h>
17*ec63e07aSXin Li #include <unistd.h>
18*ec63e07aSXin Li 
19*ec63e07aSXin Li #include <algorithm>
20*ec63e07aSXin Li #include <cstdint>
21*ec63e07aSXin Li #include <cstdlib>
22*ec63e07aSXin Li #include <cstring>
23*ec63e07aSXin Li #include <iterator>
24*ec63e07aSXin Li #include <list>
25*ec63e07aSXin Li #include <string>
26*ec63e07aSXin Li #include <type_traits>
27*ec63e07aSXin Li #include <utility>
28*ec63e07aSXin Li #include <vector>
29*ec63e07aSXin Li 
30*ec63e07aSXin Li #include "absl/base/attributes.h"
31*ec63e07aSXin Li #include "absl/base/dynamic_annotations.h"
32*ec63e07aSXin Li #include "absl/flags/parse.h"
33*ec63e07aSXin Li #include "absl/log/check.h"
34*ec63e07aSXin Li #include "absl/log/initialize.h"
35*ec63e07aSXin Li #include "absl/log/log.h"
36*ec63e07aSXin Li #include "absl/status/statusor.h"
37*ec63e07aSXin Li #include "absl/strings/str_cat.h"
38*ec63e07aSXin Li #include "google/protobuf/descriptor.h"
39*ec63e07aSXin Li #include "google/protobuf/message.h"
40*ec63e07aSXin Li #include "sandboxed_api/call.h"
41*ec63e07aSXin Li #include "sandboxed_api/lenval_core.h"
42*ec63e07aSXin Li #include "sandboxed_api/proto_arg.pb.h"
43*ec63e07aSXin Li #include "sandboxed_api/proto_helper.h"
44*ec63e07aSXin Li #include "sandboxed_api/sandbox2/comms.h"
45*ec63e07aSXin Li #include "sandboxed_api/sandbox2/forkingclient.h"
46*ec63e07aSXin Li #include "sandboxed_api/sandbox2/logsink.h"
47*ec63e07aSXin Li #include "sandboxed_api/util/raw_logging.h"
48*ec63e07aSXin Li #include "sandboxed_api/var_type.h"
49*ec63e07aSXin Li 
50*ec63e07aSXin Li #include <ffi.h>
51*ec63e07aSXin Li 
52*ec63e07aSXin Li namespace sapi {
53*ec63e07aSXin Li namespace {
54*ec63e07aSXin Li 
55*ec63e07aSXin Li // Guess the FFI type on the basis of data size and float/non-float/bool.
GetFFIType(size_t size,v::Type type)56*ec63e07aSXin Li ffi_type* GetFFIType(size_t size, v::Type type) {
57*ec63e07aSXin Li   switch (type) {
58*ec63e07aSXin Li     case v::Type::kVoid:
59*ec63e07aSXin Li       return &ffi_type_void;
60*ec63e07aSXin Li     case v::Type::kPointer:
61*ec63e07aSXin Li       return &ffi_type_pointer;
62*ec63e07aSXin Li     case v::Type::kFd:
63*ec63e07aSXin Li       return &ffi_type_sint;
64*ec63e07aSXin Li     case v::Type::kFloat:
65*ec63e07aSXin Li       if (size == sizeof(float)) {
66*ec63e07aSXin Li         return &ffi_type_float;
67*ec63e07aSXin Li       }
68*ec63e07aSXin Li       if (size == sizeof(double)) {
69*ec63e07aSXin Li         return &ffi_type_double;
70*ec63e07aSXin Li       }
71*ec63e07aSXin Li       if (size == sizeof(long double)) {
72*ec63e07aSXin Li         return &ffi_type_longdouble;
73*ec63e07aSXin Li       }
74*ec63e07aSXin Li       LOG(FATAL) << "Unsupported floating-point size: " << size;
75*ec63e07aSXin Li     case v::Type::kInt:
76*ec63e07aSXin Li       switch (size) {
77*ec63e07aSXin Li         case 1:
78*ec63e07aSXin Li           return &ffi_type_uint8;
79*ec63e07aSXin Li         case 2:
80*ec63e07aSXin Li           return &ffi_type_uint16;
81*ec63e07aSXin Li         case 4:
82*ec63e07aSXin Li           return &ffi_type_uint32;
83*ec63e07aSXin Li         case 8:
84*ec63e07aSXin Li           return &ffi_type_uint64;
85*ec63e07aSXin Li         default:
86*ec63e07aSXin Li           LOG(FATAL) << "Unsupported integral size: " << size;
87*ec63e07aSXin Li       }
88*ec63e07aSXin Li     case v::Type::kStruct:
89*ec63e07aSXin Li       LOG(FATAL) << "Structs are not supported as function arguments";
90*ec63e07aSXin Li     case v::Type::kProto:
91*ec63e07aSXin Li       LOG(FATAL) << "Protos are not supported as function arguments";
92*ec63e07aSXin Li     default:
93*ec63e07aSXin Li       LOG(FATAL) << "Unknown type: " << type << " of size: " << size;
94*ec63e07aSXin Li   }
95*ec63e07aSXin Li }
96*ec63e07aSXin Li 
97*ec63e07aSXin Li // Provides an interface to prepare the arguments for a function call.
98*ec63e07aSXin Li // In case of protobuf arguments, the class allocates and manages
99*ec63e07aSXin Li // memory for the deserialized protobuf.
100*ec63e07aSXin Li class FunctionCallPreparer {
101*ec63e07aSXin Li  public:
FunctionCallPreparer(const FuncCall & call)102*ec63e07aSXin Li   explicit FunctionCallPreparer(const FuncCall& call) {
103*ec63e07aSXin Li     CHECK(call.argc <= FuncCall::kArgsMax)
104*ec63e07aSXin Li         << "Number of arguments of a sandbox call exceeds limits.";
105*ec63e07aSXin Li     for (int i = 0; i < call.argc; ++i) {
106*ec63e07aSXin Li       arg_types_[i] = GetFFIType(call.arg_size[i], call.arg_type[i]);
107*ec63e07aSXin Li     }
108*ec63e07aSXin Li     ret_type_ = GetFFIType(call.ret_size, call.ret_type);
109*ec63e07aSXin Li     for (int i = 0; i < call.argc; ++i) {
110*ec63e07aSXin Li       if (call.arg_type[i] == v::Type::kPointer &&
111*ec63e07aSXin Li           call.aux_type[i] == v::Type::kProto) {
112*ec63e07aSXin Li         // Deserialize protobuf stored in the LenValueStruct and keep a
113*ec63e07aSXin Li         // reference to both. This way we are able to update the content of the
114*ec63e07aSXin Li         // LenValueStruct (when the sandboxee modifies the protobuf).
115*ec63e07aSXin Li         // This will also make sure that the protobuf is freed afterwards.
116*ec63e07aSXin Li         arg_values_[i] = GetDeserializedProto(
117*ec63e07aSXin Li             reinterpret_cast<LenValStruct*>(call.args[i].arg_int));
118*ec63e07aSXin Li       } else if (call.arg_type[i] == v::Type::kFloat) {
119*ec63e07aSXin Li         arg_values_[i] = reinterpret_cast<const void*>(&call.args[i].arg_float);
120*ec63e07aSXin Li       } else {
121*ec63e07aSXin Li         arg_values_[i] = reinterpret_cast<const void*>(&call.args[i].arg_int);
122*ec63e07aSXin Li       }
123*ec63e07aSXin Li     }
124*ec63e07aSXin Li   }
125*ec63e07aSXin Li 
~FunctionCallPreparer()126*ec63e07aSXin Li   ~FunctionCallPreparer() {
127*ec63e07aSXin Li     for (const auto& idx_proto : protos_to_be_destroyed_) {
128*ec63e07aSXin Li       const auto proto = idx_proto.second;
129*ec63e07aSXin Li       LenValStruct* lvs = idx_proto.first;
130*ec63e07aSXin Li       // There is no way to figure out whether the protobuf structure has
131*ec63e07aSXin Li       // changed or not, so we always serialize the protobuf again and replace
132*ec63e07aSXin Li       // the LenValStruct content.
133*ec63e07aSXin Li       std::vector<uint8_t> serialized = SerializeProto(*proto).value();
134*ec63e07aSXin Li       // Reallocate the LV memory to match its length.
135*ec63e07aSXin Li       if (lvs->size != serialized.size()) {
136*ec63e07aSXin Li         void* newdata = realloc(lvs->data, serialized.size());
137*ec63e07aSXin Li         if (!newdata) {
138*ec63e07aSXin Li           LOG(FATAL) << "Failed to reallocate protobuf buffer (size="
139*ec63e07aSXin Li                      << serialized.size() << ")";
140*ec63e07aSXin Li         }
141*ec63e07aSXin Li         lvs->size = serialized.size();
142*ec63e07aSXin Li         lvs->data = newdata;
143*ec63e07aSXin Li       }
144*ec63e07aSXin Li       memcpy(lvs->data, serialized.data(), serialized.size());
145*ec63e07aSXin Li 
146*ec63e07aSXin Li       delete proto;
147*ec63e07aSXin Li     }
148*ec63e07aSXin Li   }
149*ec63e07aSXin Li 
ret_type() const150*ec63e07aSXin Li   ffi_type* ret_type() const { return ret_type_; }
arg_types() const151*ec63e07aSXin Li   ffi_type** arg_types() const { return const_cast<ffi_type**>(arg_types_); }
arg_values() const152*ec63e07aSXin Li   void** arg_values() const { return const_cast<void**>(arg_values_); }
153*ec63e07aSXin Li 
154*ec63e07aSXin Li  private:
155*ec63e07aSXin Li   // Deserializes the protobuf argument.
GetDeserializedProto(LenValStruct * src)156*ec63e07aSXin Li   google::protobuf::MessageLite** GetDeserializedProto(LenValStruct* src) {
157*ec63e07aSXin Li     ProtoArg proto_arg;
158*ec63e07aSXin Li     if (!proto_arg.ParseFromArray(src->data, src->size)) {
159*ec63e07aSXin Li       LOG(FATAL) << "Unable to parse ProtoArg.";
160*ec63e07aSXin Li     }
161*ec63e07aSXin Li     const google::protobuf::Descriptor* desc =
162*ec63e07aSXin Li         google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(
163*ec63e07aSXin Li             proto_arg.full_name());
164*ec63e07aSXin Li     LOG_IF(FATAL, desc == nullptr) << "Unable to find the descriptor for '"
165*ec63e07aSXin Li                                    << proto_arg.full_name() << "'" << desc;
166*ec63e07aSXin Li     google::protobuf::MessageLite* deserialized_proto =
167*ec63e07aSXin Li         google::protobuf::MessageFactory::generated_factory()->GetPrototype(desc)->New();
168*ec63e07aSXin Li     LOG_IF(FATAL, deserialized_proto == nullptr)
169*ec63e07aSXin Li         << "Unable to create deserialized proto for " << proto_arg.full_name();
170*ec63e07aSXin Li     if (!deserialized_proto->ParseFromString(proto_arg.protobuf_data())) {
171*ec63e07aSXin Li       LOG(FATAL) << "Unable to deserialized proto for "
172*ec63e07aSXin Li                  << proto_arg.full_name();
173*ec63e07aSXin Li     }
174*ec63e07aSXin Li     protos_to_be_destroyed_.push_back({src, deserialized_proto});
175*ec63e07aSXin Li     return &protos_to_be_destroyed_.back().second;
176*ec63e07aSXin Li   }
177*ec63e07aSXin Li 
178*ec63e07aSXin Li   // Use list instead of vector to preserve references even with modifications.
179*ec63e07aSXin Li   // Contains pairs of lenval message pointer -> deserialized message
180*ec63e07aSXin Li   // so that we can serialize the argument again after the function call.
181*ec63e07aSXin Li   std::list<std::pair<LenValStruct*, google::protobuf::MessageLite*>>
182*ec63e07aSXin Li       protos_to_be_destroyed_;
183*ec63e07aSXin Li   ffi_type* ret_type_;
184*ec63e07aSXin Li   ffi_type* arg_types_[FuncCall::kArgsMax];
185*ec63e07aSXin Li   const void* arg_values_[FuncCall::kArgsMax];
186*ec63e07aSXin Li };
187*ec63e07aSXin Li 
188*ec63e07aSXin Li }  // namespace
189*ec63e07aSXin Li 
190*ec63e07aSXin Li namespace client {
191*ec63e07aSXin Li 
192*ec63e07aSXin Li // Error codes in the client code:
193*ec63e07aSXin Li enum class Error : uintptr_t {
194*ec63e07aSXin Li   kUnset = 0,
195*ec63e07aSXin Li   kDlOpen,
196*ec63e07aSXin Li   kDlSym,
197*ec63e07aSXin Li   kCall,
198*ec63e07aSXin Li };
199*ec63e07aSXin Li 
200*ec63e07aSXin Li // Handles requests to make function calls.
HandleCallMsg(const FuncCall & call,FuncRet * ret)201*ec63e07aSXin Li void HandleCallMsg(const FuncCall& call, FuncRet* ret) {
202*ec63e07aSXin Li   VLOG(1) << "HandleMsgCall, func: '" << call.func
203*ec63e07aSXin Li           << "', # of args: " << call.argc;
204*ec63e07aSXin Li 
205*ec63e07aSXin Li   ret->ret_type = call.ret_type;
206*ec63e07aSXin Li 
207*ec63e07aSXin Li   void* handle = dlopen(nullptr, RTLD_NOW);
208*ec63e07aSXin Li   if (handle == nullptr) {
209*ec63e07aSXin Li     LOG(ERROR) << "dlopen(nullptr, RTLD_NOW)";
210*ec63e07aSXin Li     ret->success = false;
211*ec63e07aSXin Li     ret->int_val = static_cast<uintptr_t>(Error::kDlOpen);
212*ec63e07aSXin Li     return;
213*ec63e07aSXin Li   }
214*ec63e07aSXin Li 
215*ec63e07aSXin Li   auto f = dlsym(handle, call.func);
216*ec63e07aSXin Li   if (f == nullptr) {
217*ec63e07aSXin Li     LOG(ERROR) << "Function '" << call.func << "' not found";
218*ec63e07aSXin Li     ret->success = false;
219*ec63e07aSXin Li     ret->int_val = static_cast<uintptr_t>(Error::kDlSym);
220*ec63e07aSXin Li     return;
221*ec63e07aSXin Li   }
222*ec63e07aSXin Li   FunctionCallPreparer arg_prep(call);
223*ec63e07aSXin Li   ffi_cif cif;
224*ec63e07aSXin Li   if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, call.argc, arg_prep.ret_type(),
225*ec63e07aSXin Li                    arg_prep.arg_types()) != FFI_OK) {
226*ec63e07aSXin Li     ret->success = false;
227*ec63e07aSXin Li     ret->int_val = static_cast<uintptr_t>(Error::kCall);
228*ec63e07aSXin Li     return;
229*ec63e07aSXin Li   }
230*ec63e07aSXin Li 
231*ec63e07aSXin Li   if (ret->ret_type == v::Type::kFloat) {
232*ec63e07aSXin Li     ffi_call(&cif, FFI_FN(f), &ret->float_val, arg_prep.arg_values());
233*ec63e07aSXin Li   } else {
234*ec63e07aSXin Li     ffi_call(&cif, FFI_FN(f), &ret->int_val, arg_prep.arg_values());
235*ec63e07aSXin Li   }
236*ec63e07aSXin Li 
237*ec63e07aSXin Li   ret->success = true;
238*ec63e07aSXin Li }
239*ec63e07aSXin Li 
240*ec63e07aSXin Li // Handles requests to allocate memory inside the sandboxee.
HandleAllocMsg(const size_t size,FuncRet * ret)241*ec63e07aSXin Li void HandleAllocMsg(const size_t size, FuncRet* ret) {
242*ec63e07aSXin Li   VLOG(1) << "HandleAllocMsg: size=" << size;
243*ec63e07aSXin Li 
244*ec63e07aSXin Li   const void* allocated = malloc(size);
245*ec63e07aSXin Li   // Memory is copied to the pointer using an API that the memory sanitizer
246*ec63e07aSXin Li   // is blind to (process_vm_writev). Mark the memory as initialized here, so
247*ec63e07aSXin Li   // that the sandboxed code can still be tested using MSAN.
248*ec63e07aSXin Li   ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(allocated, size);
249*ec63e07aSXin Li 
250*ec63e07aSXin Li   ret->ret_type = v::Type::kPointer;
251*ec63e07aSXin Li   ret->int_val = reinterpret_cast<uintptr_t>(allocated);
252*ec63e07aSXin Li   ret->success = true;
253*ec63e07aSXin Li }
254*ec63e07aSXin Li 
255*ec63e07aSXin Li // Like HandleAllocMsg(), but handles requests to reallocate memory.
HandleReallocMsg(uintptr_t ptr,size_t size,FuncRet * ret)256*ec63e07aSXin Li void HandleReallocMsg(uintptr_t ptr, size_t size, FuncRet* ret) {
257*ec63e07aSXin Li   VLOG(1) << "HandleReallocMsg(" << absl::StrCat(absl::Hex(ptr)) << ", " << size
258*ec63e07aSXin Li           << ")";
259*ec63e07aSXin Li 
260*ec63e07aSXin Li   const void* reallocated = realloc(reinterpret_cast<void*>(ptr), size);
261*ec63e07aSXin Li   // Memory is copied to the pointer using an API that the memory sanitizer
262*ec63e07aSXin Li   // is blind to (process_vm_writev). Mark the memory as initialized here, so
263*ec63e07aSXin Li   // that the sandboxed code can still be tested using MSAN.
264*ec63e07aSXin Li   ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(reallocated, size);
265*ec63e07aSXin Li 
266*ec63e07aSXin Li   ret->ret_type = v::Type::kPointer;
267*ec63e07aSXin Li   ret->int_val = reinterpret_cast<uintptr_t>(reallocated);
268*ec63e07aSXin Li   ret->success = true;
269*ec63e07aSXin Li }
270*ec63e07aSXin Li 
271*ec63e07aSXin Li // Handles requests to free memory previously allocated by HandleAllocMsg() and
272*ec63e07aSXin Li // HandleReallocMsg().
HandleFreeMsg(uintptr_t ptr,FuncRet * ret)273*ec63e07aSXin Li void HandleFreeMsg(uintptr_t ptr, FuncRet* ret) {
274*ec63e07aSXin Li   VLOG(1) << "HandleFreeMsg: free(0x" << absl::StrCat(absl::Hex(ptr)) << ")";
275*ec63e07aSXin Li 
276*ec63e07aSXin Li   free(reinterpret_cast<void*>(ptr));
277*ec63e07aSXin Li   ret->ret_type = v::Type::kVoid;
278*ec63e07aSXin Li   ret->success = true;
279*ec63e07aSXin Li   ret->int_val = 0ULL;
280*ec63e07aSXin Li }
281*ec63e07aSXin Li 
282*ec63e07aSXin Li // Handles requests to find a symbol value.
HandleSymbolMsg(const char * symname,FuncRet * ret)283*ec63e07aSXin Li void HandleSymbolMsg(const char* symname, FuncRet* ret) {
284*ec63e07aSXin Li   ret->ret_type = v::Type::kPointer;
285*ec63e07aSXin Li 
286*ec63e07aSXin Li   void* handle = dlopen(nullptr, RTLD_NOW);
287*ec63e07aSXin Li   if (handle == nullptr) {
288*ec63e07aSXin Li     ret->success = false;
289*ec63e07aSXin Li     ret->int_val = static_cast<uintptr_t>(Error::kDlOpen);
290*ec63e07aSXin Li     return;
291*ec63e07aSXin Li   }
292*ec63e07aSXin Li 
293*ec63e07aSXin Li   ret->int_val = reinterpret_cast<uintptr_t>(dlsym(handle, symname));
294*ec63e07aSXin Li   ret->success = true;
295*ec63e07aSXin Li }
296*ec63e07aSXin Li 
297*ec63e07aSXin Li // Handles requests to receive a file descriptor from sandboxer.
HandleSendFd(sandbox2::Comms * comms,FuncRet * ret)298*ec63e07aSXin Li void HandleSendFd(sandbox2::Comms* comms, FuncRet* ret) {
299*ec63e07aSXin Li   ret->ret_type = v::Type::kInt;
300*ec63e07aSXin Li   int fd = -1;
301*ec63e07aSXin Li 
302*ec63e07aSXin Li   if (comms->RecvFD(&fd) == false) {
303*ec63e07aSXin Li     ret->success = false;
304*ec63e07aSXin Li     return;
305*ec63e07aSXin Li   }
306*ec63e07aSXin Li 
307*ec63e07aSXin Li   ret->int_val = fd;
308*ec63e07aSXin Li   ret->success = true;
309*ec63e07aSXin Li }
310*ec63e07aSXin Li 
311*ec63e07aSXin Li // Handles requests to send a file descriptor back to sandboxer.
HandleRecvFd(sandbox2::Comms * comms,int fd_to_transfer,FuncRet * ret)312*ec63e07aSXin Li void HandleRecvFd(sandbox2::Comms* comms, int fd_to_transfer, FuncRet* ret) {
313*ec63e07aSXin Li   ret->ret_type = v::Type::kVoid;
314*ec63e07aSXin Li 
315*ec63e07aSXin Li   if (comms->SendFD(fd_to_transfer) == false) {
316*ec63e07aSXin Li     ret->success = false;
317*ec63e07aSXin Li     return;
318*ec63e07aSXin Li   }
319*ec63e07aSXin Li 
320*ec63e07aSXin Li   ret->success = true;
321*ec63e07aSXin Li }
322*ec63e07aSXin Li 
323*ec63e07aSXin Li // Handles requests to close a file descriptor in the sandboxee.
HandleCloseFd(sandbox2::Comms * comms,int fd_to_close,FuncRet * ret)324*ec63e07aSXin Li void HandleCloseFd(sandbox2::Comms* comms, int fd_to_close, FuncRet* ret) {
325*ec63e07aSXin Li   VLOG(1) << "HandleCloseFd: close(" << fd_to_close << ")";
326*ec63e07aSXin Li   close(fd_to_close);
327*ec63e07aSXin Li 
328*ec63e07aSXin Li   ret->ret_type = v::Type::kVoid;
329*ec63e07aSXin Li   ret->success = true;
330*ec63e07aSXin Li }
331*ec63e07aSXin Li 
HandleStrlen(sandbox2::Comms * comms,const char * ptr,FuncRet * ret)332*ec63e07aSXin Li void HandleStrlen(sandbox2::Comms* comms, const char* ptr, FuncRet* ret) {
333*ec63e07aSXin Li   ret->ret_type = v::Type::kInt;
334*ec63e07aSXin Li   ret->int_val = strlen(ptr);
335*ec63e07aSXin Li   ret->success = true;
336*ec63e07aSXin Li }
337*ec63e07aSXin Li 
338*ec63e07aSXin Li template <typename T>
BytesAs(const std::vector<uint8_t> & bytes)339*ec63e07aSXin Li static T BytesAs(const std::vector<uint8_t>& bytes) {
340*ec63e07aSXin Li   static_assert(std::is_trivial<T>(),
341*ec63e07aSXin Li                 "only trivial types can be used with BytesAs");
342*ec63e07aSXin Li   CHECK_EQ(bytes.size(), sizeof(T));
343*ec63e07aSXin Li   T rv;
344*ec63e07aSXin Li   memcpy(&rv, bytes.data(), sizeof(T));
345*ec63e07aSXin Li   return rv;
346*ec63e07aSXin Li }
347*ec63e07aSXin Li 
ServeRequest(sandbox2::Comms * comms)348*ec63e07aSXin Li void ServeRequest(sandbox2::Comms* comms) {
349*ec63e07aSXin Li   uint32_t tag;
350*ec63e07aSXin Li   std::vector<uint8_t> bytes;
351*ec63e07aSXin Li 
352*ec63e07aSXin Li   CHECK(comms->RecvTLV(&tag, &bytes));
353*ec63e07aSXin Li 
354*ec63e07aSXin Li   FuncRet ret{};  // Brace-init zeroes struct padding
355*ec63e07aSXin Li 
356*ec63e07aSXin Li   switch (tag) {
357*ec63e07aSXin Li     case comms::kMsgCall:
358*ec63e07aSXin Li       VLOG(1) << "Client::kMsgCall";
359*ec63e07aSXin Li       HandleCallMsg(BytesAs<FuncCall>(bytes), &ret);
360*ec63e07aSXin Li       break;
361*ec63e07aSXin Li     case comms::kMsgAllocate:
362*ec63e07aSXin Li       VLOG(1) << "Client::kMsgAllocate";
363*ec63e07aSXin Li       HandleAllocMsg(BytesAs<size_t>(bytes), &ret);
364*ec63e07aSXin Li       break;
365*ec63e07aSXin Li     case comms::kMsgReallocate:
366*ec63e07aSXin Li       VLOG(1) << "Client::kMsgReallocate";
367*ec63e07aSXin Li       {
368*ec63e07aSXin Li         auto req = BytesAs<comms::ReallocRequest>(bytes);
369*ec63e07aSXin Li         HandleReallocMsg(req.old_addr, req.size, &ret);
370*ec63e07aSXin Li       }
371*ec63e07aSXin Li       break;
372*ec63e07aSXin Li     case comms::kMsgFree:
373*ec63e07aSXin Li       VLOG(1) << "Client::kMsgFree";
374*ec63e07aSXin Li       HandleFreeMsg(BytesAs<uintptr_t>(bytes), &ret);
375*ec63e07aSXin Li       break;
376*ec63e07aSXin Li     case comms::kMsgSymbol:
377*ec63e07aSXin Li       CHECK_EQ(bytes.size(),
378*ec63e07aSXin Li                1 + std::distance(bytes.begin(),
379*ec63e07aSXin Li                                  std::find(bytes.begin(), bytes.end(), '\0')));
380*ec63e07aSXin Li       VLOG(1) << "Received Client::kMsgSymbol message";
381*ec63e07aSXin Li       HandleSymbolMsg(reinterpret_cast<const char*>(bytes.data()), &ret);
382*ec63e07aSXin Li       break;
383*ec63e07aSXin Li     case comms::kMsgExit:
384*ec63e07aSXin Li       VLOG(1) << "Received Client::kMsgExit message";
385*ec63e07aSXin Li       syscall(__NR_exit_group, 0UL);
386*ec63e07aSXin Li       break;
387*ec63e07aSXin Li     case comms::kMsgSendFd:
388*ec63e07aSXin Li       VLOG(1) << "Received Client::kMsgSendFd message";
389*ec63e07aSXin Li       HandleSendFd(comms, &ret);
390*ec63e07aSXin Li       break;
391*ec63e07aSXin Li     case comms::kMsgRecvFd:
392*ec63e07aSXin Li       VLOG(1) << "Received Client::kMsgRecvFd message";
393*ec63e07aSXin Li       HandleRecvFd(comms, BytesAs<int>(bytes), &ret);
394*ec63e07aSXin Li       break;
395*ec63e07aSXin Li     case comms::kMsgClose:
396*ec63e07aSXin Li       VLOG(1) << "Received Client::kMsgClose message";
397*ec63e07aSXin Li       HandleCloseFd(comms, BytesAs<int>(bytes), &ret);
398*ec63e07aSXin Li       break;
399*ec63e07aSXin Li     case comms::kMsgStrlen:
400*ec63e07aSXin Li       VLOG(1) << "Received Client::kMsgStrlen message";
401*ec63e07aSXin Li       HandleStrlen(comms, BytesAs<const char*>(bytes), &ret);
402*ec63e07aSXin Li       break;
403*ec63e07aSXin Li       break;
404*ec63e07aSXin Li     default:
405*ec63e07aSXin Li       LOG(FATAL) << "Received unknown tag: " << tag;
406*ec63e07aSXin Li       break;  // Not reached
407*ec63e07aSXin Li   }
408*ec63e07aSXin Li 
409*ec63e07aSXin Li   if (ret.ret_type == v::Type::kFloat) {
410*ec63e07aSXin Li     // Make MSAN happy with long double.
411*ec63e07aSXin Li     ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(&ret.float_val, sizeof(ret.float_val));
412*ec63e07aSXin Li     VLOG(1) << "Returned value: " << ret.float_val
413*ec63e07aSXin Li             << ", Success: " << (ret.success ? "Yes" : "No");
414*ec63e07aSXin Li   } else {
415*ec63e07aSXin Li     VLOG(1) << "Returned value: " << ret.int_val << " (0x"
416*ec63e07aSXin Li             << absl::StrCat(absl::Hex(ret.int_val))
417*ec63e07aSXin Li             << "), Success: " << (ret.success ? "Yes" : "No");
418*ec63e07aSXin Li   }
419*ec63e07aSXin Li 
420*ec63e07aSXin Li   CHECK(comms->SendTLV(comms::kMsgReturn, sizeof(ret),
421*ec63e07aSXin Li                        reinterpret_cast<uint8_t*>(&ret)));
422*ec63e07aSXin Li }
423*ec63e07aSXin Li 
424*ec63e07aSXin Li }  // namespace client
425*ec63e07aSXin Li }  // namespace sapi
426*ec63e07aSXin Li 
main(int argc,char * argv[])427*ec63e07aSXin Li ABSL_ATTRIBUTE_WEAK int main(int argc, char* argv[]) {
428*ec63e07aSXin Li   absl::ParseCommandLine(argc, argv);
429*ec63e07aSXin Li   absl::InitializeLog();
430*ec63e07aSXin Li 
431*ec63e07aSXin Li   // Note regarding the FD usage here: Parent and child seem to make use of the
432*ec63e07aSXin Li   // same FD, although this is not true. During process setup `dup2()` will be
433*ec63e07aSXin Li   // called to replace the FD `kSandbox2ClientCommsFD`.
434*ec63e07aSXin Li   // We do not use a new comms object here as the destructor would close our FD.
435*ec63e07aSXin Li   sandbox2::Comms comms(sandbox2::Comms::kDefaultConnection);
436*ec63e07aSXin Li   sandbox2::ForkingClient s2client(&comms);
437*ec63e07aSXin Li 
438*ec63e07aSXin Li   // Forkserver loop.
439*ec63e07aSXin Li   while (true) {
440*ec63e07aSXin Li     pid_t pid = s2client.WaitAndFork();
441*ec63e07aSXin Li     if (pid == -1) {
442*ec63e07aSXin Li       LOG(FATAL) << "Could not spawn a new sandboxee";
443*ec63e07aSXin Li     }
444*ec63e07aSXin Li     if (pid == 0) {
445*ec63e07aSXin Li       break;
446*ec63e07aSXin Li     }
447*ec63e07aSXin Li   }
448*ec63e07aSXin Li 
449*ec63e07aSXin Li   // Child thread.
450*ec63e07aSXin Li   s2client.SandboxMeHere();
451*ec63e07aSXin Li 
452*ec63e07aSXin Li   // Enable log forwarding if enabled by the sandboxer.
453*ec63e07aSXin Li   if (s2client.HasMappedFD(sandbox2::LogSink::kLogFDName)) {
454*ec63e07aSXin Li     s2client.SendLogsToSupervisor();
455*ec63e07aSXin Li   }
456*ec63e07aSXin Li 
457*ec63e07aSXin Li   // Run SAPI stub.
458*ec63e07aSXin Li   while (true) {
459*ec63e07aSXin Li     sapi::client::ServeRequest(&comms);
460*ec63e07aSXin Li   }
461*ec63e07aSXin Li   LOG(FATAL) << "Unreachable";
462*ec63e07aSXin Li }
463