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