Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / components / nacl / loader / nonsfi / nonsfi_main.cc
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