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"
27 typedef void (*EntryPointType
)(uintptr_t*);
29 class PluginMainDelegate
: public base::PlatformThread::Delegate
{
31 explicit PluginMainDelegate(EntryPointType entry_point
)
32 : entry_point_(entry_point
) {
35 virtual ~PluginMainDelegate() {
38 virtual void ThreadMain() OVERRIDE
{
39 base::PlatformThread::SetName("NaClMainThread");
42 0, // Do not use fini.
45 0, // Null terminate for argv.
46 0, // Null terminate for envv.
48 reinterpret_cast<uintptr_t>(&NaClIrtInterface
),
50 0, // Null terminate for auxv.
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 {
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
);
76 if (image
.Read(desc
.get()) != LOAD_OK
) {
77 LOG(ERROR
) << "LoadModuleRpc: Failed to read binary.";
81 if (image
.Load(desc
.get()) != LOAD_OK
) {
82 LOG(ERROR
) << "LoadModuleRpc: Failed to load the image";
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.";
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
,
147 struct NaClImcTypedMsgHdr hdr
;
148 hdr
.iov
= static_cast<struct NaClImcMsgIoVec
*>(NULL
);
151 hdr
.ndesc_length
= NACL_ARRAY_SIZE(descs
);
154 ssize_t error
= (*NACL_VTBL(NaClDesc
, channel
)->SendMsg
)(
155 reinterpret_cast<struct NaClDesc
*>(channel
), &hdr
, 0);
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
);
167 LOG(ERROR
) << "ServiceAccept: Failed to accept " << status
;
171 NaClSrpcServerLoop(connected_desc
, kNonSfiServiceHandlers
, NULL
);
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(
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()));
192 LOG(ERROR
) << "MainStart: Failed to set up bootstrap channel.";
196 // Start the SRPC server loop.
197 ServiceAccept(secure_port
.get());
200 } // namespace nonsfi