Connect PPAPI IPC channels for non-SFI mode.
[chromium-blink-merge.git] / components / nacl / loader / nonsfi / nonsfi_main.cc
blob87fbc1b734917b6b9c523e950bf5e192bf0f86a8
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.
5 #include "components/nacl/loader/nonsfi/nonsfi_main.h"
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 "components/nacl/loader/nonsfi/elf_loader.h"
12 #include "components/nacl/loader/nonsfi/irt_interfaces.h"
13 #include "native_client/src/include/elf_auxv.h"
14 #include "native_client/src/include/nacl_macros.h"
15 #include "native_client/src/public/secure_service.h"
16 #include "native_client/src/shared/srpc/nacl_srpc.h"
17 #include "native_client/src/trusted/desc/nacl_desc_base.h"
18 #include "native_client/src/trusted/desc/nacl_desc_imc.h"
19 #include "native_client/src/trusted/desc/nrd_all_modules.h"
20 #include "native_client/src/trusted/desc/nrd_xfer.h"
21 #include "native_client/src/trusted/service_runtime/nacl_error_code.h"
23 namespace nacl {
24 namespace nonsfi {
25 namespace {
27 typedef void (*EntryPointType)(uintptr_t*);
29 class PluginMainDelegate : public base::PlatformThread::Delegate {
30 public:
31 explicit PluginMainDelegate(EntryPointType entry_point)
32 : entry_point_(entry_point) {
35 virtual ~PluginMainDelegate() {
38 virtual void ThreadMain() OVERRIDE {
39 base::PlatformThread::SetName("NaClMainThread");
41 uintptr_t info[] = {
42 0, // Do not use fini.
43 0, // envc.
44 0, // argc.
45 0, // Null terminate for argv.
46 0, // Null terminate for envv.
47 AT_SYSINFO,
48 reinterpret_cast<uintptr_t>(&NaClIrtInterface),
49 AT_NULL,
50 0, // Null terminate for auxv.
52 entry_point_(info);
55 private:
56 EntryPointType entry_point_;
59 // Default stack size of the plugin main thread. We heuristically chose 16M.
60 const size_t kStackSize = (16 << 20);
62 struct NaClDescUnrefer {
63 void operator()(struct NaClDesc* desc) const {
64 NaClDescUnref(desc);
68 void LoadModuleRpc(struct NaClSrpcRpc* rpc,
69 struct NaClSrpcArg** in_args,
70 struct NaClSrpcArg** out_args,
71 struct NaClSrpcClosure* done_cls) {
72 rpc->result = NACL_SRPC_RESULT_INTERNAL;
74 ::scoped_ptr<struct NaClDesc, NaClDescUnrefer> desc(in_args[0]->u.hval);
75 ElfImage image;
76 if (image.Read(desc.get()) != LOAD_OK) {
77 LOG(ERROR) << "LoadModuleRpc: Failed to read binary.";
78 return;
81 if (image.Load(desc.get()) != LOAD_OK) {
82 LOG(ERROR) << "LoadModuleRpc: Failed to load the image";
83 return;
86 EntryPointType entry_point =
87 reinterpret_cast<EntryPointType>(image.entry_point());
88 if (!base::PlatformThread::CreateNonJoinable(
89 kStackSize, new PluginMainDelegate(entry_point))) {
90 LOG(ERROR) << "LoadModuleRpc: Failed to create plugin main thread.";
91 return;
94 rpc->result = NACL_SRPC_RESULT_OK;
95 (*done_cls->Run)(done_cls);
98 const static struct NaClSrpcHandlerDesc kNonSfiServiceHandlers[] = {
99 { NACL_SECURE_SERVICE_LOAD_MODULE, LoadModuleRpc, },
100 { static_cast<const char*>(NULL), static_cast<NaClSrpcMethod>(NULL), },
103 // Creates two socketpairs to communicate with the host process.
104 void CreateSecureSocketPair(struct NaClDesc* secure_pair[2],
105 struct NaClDesc* pair[2]) {
106 // Set up a secure pair.
107 if (NaClCommonDescMakeBoundSock(secure_pair)) {
108 LOG(FATAL) << "Cound not create secure service socket\n";
111 // Set up a service pair.
112 if (NaClCommonDescMakeBoundSock(pair)) {
113 LOG(FATAL) << "Could not create service socket";
117 // Wraps handle by NaClDesc, and sends secure_service_address and
118 // service_address via the created descriptor.
119 struct NaClDesc* SetUpBootstrapChannel(NaClHandle handle,
120 struct NaClDesc* secure_service_address,
121 struct NaClDesc* service_address) {
122 if (secure_service_address == NULL) {
123 LOG(FATAL) << "SetUpBootstrapChannel: secure_service_address is not set";
126 if (service_address == NULL) {
127 LOG(FATAL) << "SetUpBootstrapChannel: secure_service_address is not set";
130 struct NaClDescImcDesc* channel =
131 static_cast<struct NaClDescImcDesc*>(malloc(sizeof *channel));
132 if (channel == NULL) {
133 LOG(FATAL) << "SetUpBootstrapChannel: no memory";
136 if (!NaClDescImcDescCtor(channel, handle)) {
137 LOG(FATAL) << "SetUpBootstrapChannel: cannot construct IMC descriptor "
138 << "object for inherited descriptor: " << handle;
141 // Send the descriptors to the host.
142 struct NaClDesc* descs[2] = {
143 secure_service_address,
144 service_address,
147 struct NaClImcTypedMsgHdr hdr;
148 hdr.iov = static_cast<struct NaClImcMsgIoVec*>(NULL);
149 hdr.iov_length = 0;
150 hdr.ndescv = descs;
151 hdr.ndesc_length = NACL_ARRAY_SIZE(descs);
152 hdr.flags = 0;
154 ssize_t error = (*NACL_VTBL(NaClDesc, channel)->SendMsg)(
155 reinterpret_cast<struct NaClDesc*>(channel), &hdr, 0);
156 if (error) {
157 LOG(FATAL) << "SetUpBootstrapChannel: SendMsg failed, error = " << error;
159 return reinterpret_cast<struct NaClDesc*>(channel);
162 // Starts to listen to the port and runs the server loop.
163 void ServiceAccept(struct NaClDesc* port) {
164 struct NaClDesc* connected_desc = NULL;
165 int status = (*NACL_VTBL(NaClDesc, port)->AcceptConn)(port, &connected_desc);
166 if (status) {
167 LOG(ERROR) << "ServiceAccept: Failed to accept " << status;
168 return;
171 NaClSrpcServerLoop(connected_desc, kNonSfiServiceHandlers, NULL);
174 } // namespace
176 void MainStart(NaClHandle imc_bootstrap_handle) {
177 NaClSrpcModuleInit();
179 struct NaClDesc* secure_pair[2] = { NULL, NULL };
180 struct NaClDesc* pair[2] = { NULL, NULL };
181 CreateSecureSocketPair(secure_pair, pair);
182 ::scoped_ptr<struct NaClDesc, NaClDescUnrefer> secure_port(secure_pair[0]);
183 ::scoped_ptr<struct NaClDesc, NaClDescUnrefer> secure_address(
184 secure_pair[1]);
185 ::scoped_ptr<struct NaClDesc, NaClDescUnrefer> service_port(pair[0]);
186 ::scoped_ptr<struct NaClDesc, NaClDescUnrefer> service_address(pair[1]);
188 ::scoped_ptr<struct NaClDesc, NaClDescUnrefer> channel(
189 SetUpBootstrapChannel(imc_bootstrap_handle,
190 secure_address.get(), service_address.get()));
191 if (!channel) {
192 LOG(ERROR) << "MainStart: Failed to set up bootstrap channel.";
193 return;
196 // Start the SRPC server loop.
197 ServiceAccept(secure_port.get());
200 } // namespace nonsfi
201 } // namespace nacl