Home | History | Annotate | Download | only in nonsfi
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "components/nacl/loader/nonsfi/nonsfi_main.h"
      6 
      7 #include "base/debug/leak_annotations.h"
      8 #include "base/logging.h"
      9 #include "base/memory/scoped_ptr.h"
     10 #include "base/threading/platform_thread.h"
     11 #include "base/threading/thread_restrictions.h"
     12 #include "components/nacl/loader/nonsfi/elf_loader.h"
     13 #include "components/nacl/loader/nonsfi/irt_interfaces.h"
     14 #include "native_client/src/include/elf_auxv.h"
     15 #include "native_client/src/include/nacl_macros.h"
     16 #include "native_client/src/public/secure_service.h"
     17 #include "native_client/src/shared/srpc/nacl_srpc.h"
     18 #include "native_client/src/trusted/desc/nacl_desc_base.h"
     19 #include "native_client/src/trusted/desc/nacl_desc_imc.h"
     20 #include "native_client/src/trusted/desc/nrd_all_modules.h"
     21 #include "native_client/src/trusted/desc/nrd_xfer.h"
     22 #include "native_client/src/trusted/service_runtime/nacl_error_code.h"
     23 #include "ppapi/nacl_irt/plugin_startup.h"
     24 
     25 namespace nacl {
     26 namespace nonsfi {
     27 namespace {
     28 
     29 typedef void (*EntryPointType)(uintptr_t*);
     30 
     31 class PluginMainDelegate : public base::PlatformThread::Delegate {
     32  public:
     33   explicit PluginMainDelegate(EntryPointType entry_point)
     34       : entry_point_(entry_point) {
     35   }
     36 
     37   virtual ~PluginMainDelegate() {
     38   }
     39 
     40   virtual void ThreadMain() OVERRIDE {
     41     base::PlatformThread::SetName("NaClMainThread");
     42 
     43     // This will only happen once per process, so we give the permission to
     44     // create Singletons.
     45     base::ThreadRestrictions::SetSingletonAllowed(true);
     46     uintptr_t info[] = {
     47       0,  // Do not use fini.
     48       0,  // envc.
     49       0,  // argc.
     50       0,  // Null terminate for argv.
     51       0,  // Null terminate for envv.
     52       AT_SYSINFO,
     53       reinterpret_cast<uintptr_t>(&NaClIrtInterface),
     54       AT_NULL,
     55       0,  // Null terminate for auxv.
     56     };
     57     entry_point_(info);
     58   }
     59 
     60  private:
     61   EntryPointType entry_point_;
     62 };
     63 
     64 // Default stack size of the plugin main thread. We heuristically chose 16M.
     65 const size_t kStackSize = (16 << 20);
     66 
     67 struct NaClDescUnrefer {
     68   void operator()(struct NaClDesc* desc) const {
     69     NaClDescUnref(desc);
     70   }
     71 };
     72 
     73 void LoadModuleRpc(struct NaClSrpcRpc* rpc,
     74                    struct NaClSrpcArg** in_args,
     75                    struct NaClSrpcArg** out_args,
     76                    struct NaClSrpcClosure* done_cls) {
     77   rpc->result = NACL_SRPC_RESULT_INTERNAL;
     78 
     79   ::scoped_ptr<struct NaClDesc, NaClDescUnrefer> desc(in_args[0]->u.hval);
     80   ElfImage image;
     81   if (image.Read(desc.get()) != LOAD_OK) {
     82     LOG(ERROR) << "LoadModuleRpc: Failed to read binary.";
     83     return;
     84   }
     85 
     86   if (image.Load(desc.get()) != LOAD_OK) {
     87     LOG(ERROR) << "LoadModuleRpc: Failed to load the image";
     88     return;
     89   }
     90 
     91   EntryPointType entry_point =
     92       reinterpret_cast<EntryPointType>(image.entry_point());
     93   if (!base::PlatformThread::CreateNonJoinable(
     94           kStackSize, new PluginMainDelegate(entry_point))) {
     95     LOG(ERROR) << "LoadModuleRpc: Failed to create plugin main thread.";
     96     return;
     97   }
     98 
     99   rpc->result = NACL_SRPC_RESULT_OK;
    100   (*done_cls->Run)(done_cls);
    101 }
    102 
    103 const static struct NaClSrpcHandlerDesc kNonSfiServiceHandlers[] = {
    104   { NACL_SECURE_SERVICE_LOAD_MODULE, LoadModuleRpc, },
    105   { static_cast<const char*>(NULL), static_cast<NaClSrpcMethod>(NULL), },
    106 };
    107 
    108 // Creates two socketpairs to communicate with the host process.
    109 void CreateSecureSocketPair(struct NaClDesc* secure_pair[2],
    110                             struct NaClDesc* pair[2]) {
    111   // Set up a secure pair.
    112   if (NaClCommonDescMakeBoundSock(secure_pair)) {
    113     LOG(FATAL) << "Cound not create secure service socket\n";
    114   }
    115 
    116   // Set up a service pair.
    117   if (NaClCommonDescMakeBoundSock(pair)) {
    118     LOG(FATAL) << "Could not create service socket";
    119   }
    120 }
    121 
    122 // Wraps handle by NaClDesc, and sends secure_service_address and
    123 // service_address via the created descriptor.
    124 struct NaClDesc* SetUpBootstrapChannel(NaClHandle handle,
    125                                        struct NaClDesc* secure_service_address,
    126                                        struct NaClDesc* service_address) {
    127   if (secure_service_address == NULL) {
    128     LOG(FATAL) << "SetUpBootstrapChannel: secure_service_address is not set";
    129   }
    130 
    131   if (service_address == NULL) {
    132     LOG(FATAL) << "SetUpBootstrapChannel: secure_service_address is not set";
    133   }
    134 
    135   struct NaClDescImcDesc* channel =
    136       static_cast<struct NaClDescImcDesc*>(malloc(sizeof *channel));
    137   if (channel == NULL) {
    138     LOG(FATAL) << "SetUpBootstrapChannel: no memory";
    139   }
    140 
    141   if (!NaClDescImcDescCtor(channel, handle)) {
    142     LOG(FATAL) << "SetUpBootstrapChannel: cannot construct IMC descriptor "
    143                << "object for inherited descriptor: " << handle;
    144   }
    145 
    146   // Send the descriptors to the host.
    147   struct NaClDesc* descs[2] = {
    148     secure_service_address,
    149     service_address,
    150   };
    151 
    152   struct NaClImcTypedMsgHdr hdr;
    153   hdr.iov = static_cast<struct NaClImcMsgIoVec*>(NULL);
    154   hdr.iov_length = 0;
    155   hdr.ndescv = descs;
    156   hdr.ndesc_length = NACL_ARRAY_SIZE(descs);
    157   hdr.flags = 0;
    158 
    159   ssize_t error = (*NACL_VTBL(NaClDesc, channel)->SendMsg)(
    160       reinterpret_cast<struct NaClDesc*>(channel), &hdr, 0);
    161   if (error) {
    162     LOG(FATAL) << "SetUpBootstrapChannel: SendMsg failed, error = " << error;
    163   }
    164   return reinterpret_cast<struct NaClDesc*>(channel);
    165 }
    166 
    167 // Starts to listen to the port and runs the server loop.
    168 void ServiceAccept(struct NaClDesc* port) {
    169   struct NaClDesc* connected_desc = NULL;
    170   int status = (*NACL_VTBL(NaClDesc, port)->AcceptConn)(port, &connected_desc);
    171   if (status) {
    172     LOG(ERROR) << "ServiceAccept: Failed to accept " << status;
    173     return;
    174   }
    175 
    176   NaClSrpcServerLoop(connected_desc, kNonSfiServiceHandlers, NULL);
    177 }
    178 
    179 }  // namespace
    180 
    181 void MainStart(NaClHandle imc_bootstrap_handle) {
    182   NaClSrpcModuleInit();
    183 
    184   struct NaClDesc* secure_pair[2] = { NULL, NULL };
    185   struct NaClDesc* pair[2] = { NULL, NULL };
    186   CreateSecureSocketPair(secure_pair, pair);
    187   ::scoped_ptr<struct NaClDesc, NaClDescUnrefer> secure_port(secure_pair[0]);
    188   ::scoped_ptr<struct NaClDesc, NaClDescUnrefer> secure_address(
    189        secure_pair[1]);
    190   ::scoped_ptr<struct NaClDesc, NaClDescUnrefer> service_port(pair[0]);
    191   ::scoped_ptr<struct NaClDesc, NaClDescUnrefer> service_address(pair[1]);
    192 
    193   ::scoped_ptr<struct NaClDesc, NaClDescUnrefer> channel(
    194        SetUpBootstrapChannel(imc_bootstrap_handle,
    195                              secure_address.get(), service_address.get()));
    196   if (!channel) {
    197     LOG(ERROR) << "MainStart: Failed to set up bootstrap channel.";
    198     return;
    199   }
    200 
    201   // Start the SRPC server loop.
    202   ServiceAccept(secure_port.get());
    203 }
    204 
    205 }  // namespace nonsfi
    206 }  // namespace nacl
    207