1 : /*
2 : * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 : * Use of this source code is governed by a BSD-style license that can be
4 : * found in the LICENSE file.
5 : */
6 :
7 : #include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h"
8 :
9 : #include "native_client/src/include/nacl_macros.h"
10 : #include "native_client/src/public/secure_service.h"
11 : #include "native_client/src/shared/platform/nacl_check.h"
12 : #include "native_client/src/shared/srpc/nacl_srpc.h"
13 :
14 :
15 : namespace nacl {
16 :
17 : SelLdrLauncherBase::SelLdrLauncherBase()
18 : : channel_(NACL_INVALID_HANDLE),
19 : bootstrap_socket_(NULL),
20 : secure_socket_addr_(NULL),
21 60 : socket_addr_(NULL) {
22 20 : }
23 :
24 13 : SelLdrLauncherBase::~SelLdrLauncherBase() {
25 13 : if (NACL_INVALID_HANDLE != channel_) {
26 0 : NaClClose(channel_);
27 0 : }
28 52 : }
29 :
30 : bool SelLdrLauncherBase::ConnectBootstrapSocket() {
31 60 : CHECK(factory_ == NULL);
32 40 : factory_.reset(new DescWrapperFactory);
33 60 : CHECK(channel_ != NACL_INVALID_HANDLE);
34 20 : bootstrap_socket_.reset(factory_->MakeImcSock(channel_));
35 20 : if (bootstrap_socket_ == NULL) {
36 0 : return false;
37 : }
38 : // bootstrap_socket_ now has ownership of channel_, so we get rid of
39 : // our "reference" to it.
40 20 : channel_ = NACL_INVALID_HANDLE;
41 :
42 20 : return true;
43 20 : }
44 :
45 : bool SelLdrLauncherBase::RetrieveSockAddr() {
46 20 : DescWrapper::MsgHeader header;
47 20 : DescWrapper::MsgIoVec iovec[1];
48 20 : DescWrapper* descs[NACL_ABI_IMC_USER_DESC_MAX];
49 20 : scoped_array<unsigned char> bytes(
50 : new unsigned char[NACL_ABI_IMC_USER_BYTES_MAX]);
51 40 : if (bytes.get() == NULL) {
52 0 : return false;
53 : }
54 :
55 : // Set up to receive a message.
56 40 : iovec[0].base = bytes.get();
57 20 : iovec[0].length = NACL_ABI_IMC_USER_BYTES_MAX;
58 20 : header.iov = iovec;
59 20 : header.iov_length = NACL_ARRAY_SIZE(iovec);
60 20 : header.ndescv = descs;
61 20 : header.ndescv_length = NACL_ARRAY_SIZE(descs);
62 20 : header.flags = 0;
63 : // Receive the message.
64 60 : ssize_t received = bootstrap_socket_->RecvMsg(&header, 0, NULL);
65 20 : if (0 != received) {
66 0 : NaClLog(LOG_ERROR, "SelLdrLauncherBase::RetrieveSockAddr: "
67 : "RecvMsg() returned %d\n", static_cast<int>(received));
68 0 : return false;
69 : }
70 : // Check that there were exactly two descriptors passed.
71 20 : if (2 != header.ndescv_length) {
72 0 : NaClLog(LOG_ERROR, "SelLdrLauncherBase::RetrieveSockAddr: "
73 : "got desc count %d, expected 2\n",
74 : static_cast<int>(header.ndescv_length));
75 0 : return false;
76 : }
77 20 : secure_socket_addr_.reset(descs[0]);
78 20 : socket_addr_.reset(descs[1]);
79 :
80 40 : return true;
81 20 : }
82 :
83 18 : bool SelLdrLauncherBase::SetupCommand(NaClSrpcChannel* command) {
84 : // Get the bootstrap socket.
85 18 : if (!ConnectBootstrapSocket()) {
86 0 : NaClLog(LOG_ERROR, "SelLdrLauncherBase::SetupCommand: "
87 : "getting bootstrap socket failed\n");
88 0 : return false;
89 : }
90 : // Get the socket address from the descriptor.
91 18 : if (!RetrieveSockAddr()) {
92 0 : NaClLog(LOG_ERROR, "SelLdrLauncherBase::SetupCommand: "
93 : "getting sel_ldr socket address failed\n");
94 0 : return false;
95 : }
96 : // Connect to the trusted command channel.
97 18 : scoped_ptr<DescWrapper> command_desc(secure_socket_addr_->Connect());
98 36 : if (command_desc == NULL) {
99 0 : NaClLog(LOG_ERROR, "SelLdrLauncherBase::SetupCommand: Connect() failed\n");
100 0 : return false;
101 : }
102 : // Start the SRPC client to communicate with the trusted command channel.
103 : // SRPC client takes an additional reference to command_desc.
104 72 : if (!NaClSrpcClientCtor(command, command_desc->desc())) {
105 0 : NaClLog(LOG_ERROR, "SelLdrLauncherBase::SetupCommand: "
106 : "NaClSrpcClientCtor failed\n");
107 0 : return false;
108 : }
109 18 : return true;
110 36 : }
111 :
112 16 : bool SelLdrLauncherBase::LoadModule(NaClSrpcChannel* command,
113 16 : DescWrapper* nexe) {
114 48 : CHECK(nexe != NULL);
115 : // Load module over command channel.
116 16 : NaClSrpcResultCodes rpc_result =
117 32 : NaClSrpcInvokeBySignature(command,
118 : NACL_SECURE_SERVICE_LOAD_MODULE,
119 16 : nexe->desc());
120 16 : if (NACL_SRPC_RESULT_OK != rpc_result) {
121 0 : NaClLog(LOG_ERROR, "SelLdrLauncherBase::LoadModule: "
122 : "rpc_result=%d is not successful\n",
123 : static_cast<int>(rpc_result));
124 0 : NaClSrpcDtor(command);
125 0 : return false;
126 : }
127 16 : return true;
128 16 : }
129 :
130 2 : bool SelLdrLauncherBase::SetupCommandAndLoad(NaClSrpcChannel* command,
131 2 : DescWrapper* nexe) {
132 2 : if (!SetupCommand(command)) {
133 0 : return false;
134 : }
135 2 : if (nexe != NULL) {
136 2 : if (!LoadModule(command, nexe)) {
137 0 : return false;
138 : }
139 2 : }
140 2 : return true;
141 2 : }
142 :
143 18 : bool SelLdrLauncherBase::StartModule(NaClSrpcChannel* command) {
144 : // Start untrusted code module.
145 18 : int start_result;
146 18 : NaClSrpcResultCodes rpc_result = NaClSrpcInvokeBySignature(
147 : command,
148 : NACL_SECURE_SERVICE_START_MODULE,
149 : &start_result);
150 18 : NaClLog(4, "SelLdrLauncher::StartModule rpc result %d\n",
151 : static_cast<int>(rpc_result));
152 36 : if (NACL_SRPC_RESULT_OK != rpc_result || LOAD_OK != start_result) {
153 0 : NaClSrpcDtor(command);
154 0 : NaClLog(LOG_ERROR, "SelLdrLauncherBase::StartModule: "
155 : "start_module failed: rpc_result=%d, start_result=%d (%s)\n",
156 : static_cast<int>(rpc_result), start_result,
157 0 : NaClErrorString(static_cast<NaClErrorCode>(start_result)));
158 0 : return false;
159 : }
160 18 : return true;
161 18 : }
162 :
163 11 : bool SelLdrLauncherBase::SetupAppChannel(NaClSrpcChannel* out_app_chan) {
164 : // Connect to the untrusted service itself.
165 11 : scoped_ptr<DescWrapper> untrusted_desc(socket_addr_->Connect());
166 22 : if (untrusted_desc == NULL) {
167 0 : NaClLog(LOG_ERROR, "SelLdrLauncher::StartModuleAndSetupAppChannel: "
168 : "Connect failed\n");
169 0 : return false;
170 : }
171 : // Start the SRPC client to communicate with the untrusted service
172 : // SRPC client takes an additional reference to untrusted_desc.
173 44 : if (!NaClSrpcClientCtor(out_app_chan, untrusted_desc->desc())) {
174 1 : NaClLog(LOG_ERROR, "SelLdrLauncherBase::SetupAppChannel: "
175 : "NaClSrpcClientCtor failed\n");
176 1 : return false;
177 : }
178 21 : return true;
179 11 : }
180 :
181 : // Sends the SRPC to start the nexe over |command| and sets up the application
182 : // SRPC chanel |out_app_chan|.
183 : bool SelLdrLauncherBase::StartModuleAndSetupAppChannel(
184 4 : NaClSrpcChannel* command,
185 4 : NaClSrpcChannel* out_app_chan) {
186 4 : if (!StartModule(command)) {
187 0 : return false;
188 : }
189 0 : if (!SetupAppChannel(out_app_chan)) {
190 0 : return false;
191 : }
192 0 : return true;
193 0 : }
194 :
195 0 : DescWrapper* SelLdrLauncherBase::Wrap(NaClDesc* raw_desc) {
196 0 : CHECK(factory_ != NULL);
197 0 : return factory_->MakeGeneric(raw_desc);
198 : }
199 :
200 5 : DescWrapper* SelLdrLauncherBase::WrapCleanup(NaClDesc* raw_desc) {
201 15 : CHECK(factory_ != NULL);
202 5 : return factory_->MakeGenericCleanup(raw_desc);
203 : }
204 :
205 : nacl::string SelLdrLauncherBase::GetCrashLogOutput() {
206 0 : DescWrapper::MsgHeader hdr;
207 0 : DescWrapper::MsgIoVec iov;
208 0 : char msg_buf[1024];
209 0 : ssize_t nbytes = 0;
210 :
211 0 : iov.base = msg_buf;
212 0 : iov.length = sizeof msg_buf;
213 0 : hdr.iov = &iov;
214 0 : hdr.iov_length = 1;
215 0 : hdr.ndescv = NULL;
216 0 : hdr.ndescv_length = 0;
217 0 : hdr.flags = 0;
218 0 : if (NULL != bootstrap_socket_.get()) {
219 0 : nbytes = bootstrap_socket_->RecvMsg(&hdr, 0, NULL);
220 0 : }
221 0 : if (nbytes > 0) {
222 0 : return nacl::string(msg_buf, nbytes);
223 : }
224 0 : return "";
225 0 : }
226 :
227 : } // namespace nacl
|