1 : /* -*- c++ -*- */
2 : /*
3 : * Copyright (c) 2012 The Native Client Authors. All rights reserved.
4 : * Use of this source code is governed by a BSD-style license that can be
5 : * found in the LICENSE file.
6 : */
7 :
8 :
9 : // Utility class for launching sel_ldr.
10 :
11 : #ifndef NATIVE_CLIENT_SRC_TRUSTED_NONNACL_UTIL_SEL_LDR_LAUNCHER_H_
12 : #define NATIVE_CLIENT_SRC_TRUSTED_NONNACL_UTIL_SEL_LDR_LAUNCHER_H_
13 :
14 : #include <vector>
15 :
16 : #include "native_client/src/include/nacl_scoped_ptr.h"
17 : #include "native_client/src/include/nacl_string.h"
18 : #include "native_client/src/include/portability.h"
19 : #include "native_client/src/shared/imc/nacl_imc_c.h"
20 : #include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
21 : #include "native_client/src/trusted/service_runtime/nacl_error_code.h"
22 :
23 : struct NaClSrpcChannel;
24 : struct NaClDesc;
25 :
26 : namespace nacl {
27 : // TODO(robertm): Move this to new header if it becomes more popular.
28 0 : template <class T> nacl::string ToString(const T& t) {
29 0 : nacl::stringstream ss;
30 0 : ss << t;
31 0 : return ss.str();
32 0 : }
33 :
34 : /*
35 : * This class defines an interface that locates sel_ldr.
36 : */
37 : class SelLdrLocator {
38 : public:
39 : // Returns a directory with sel_ldr.
40 : virtual void GetDirectory(char* buffer, size_t len) = 0;
41 :
42 16 : SelLdrLocator() {}
43 :
44 13 : virtual ~SelLdrLocator() {}
45 :
46 : DISALLOW_COPY_AND_ASSIGN(SelLdrLocator);
47 : };
48 :
49 : /*
50 : * Default implementation of SelLdrLocator which tries to
51 : * locate a browser plugin. Default constructor of SelLdrLauncher use it.
52 : */
53 52 : class PluginSelLdrLocator : public SelLdrLocator {
54 : public:
55 : // We have different implementations for all platforms.
56 : virtual void GetDirectory(char* buffer, size_t len);
57 :
58 32 : PluginSelLdrLocator() {}
59 :
60 : DISALLOW_COPY_AND_ASSIGN(PluginSelLdrLocator);
61 : };
62 :
63 : /*
64 : * This class encapsulates the process of launching an instance of sel_ldr
65 : * to communicate with the NaCl plugin over an IMC channel.
66 : *
67 : * The sel_ldr process can be forked directly using a command line of args
68 : * or by sending a message to the (Chrome) browser process.
69 : */
70 : class SelLdrLauncherBase {
71 : public:
72 : SelLdrLauncherBase();
73 : virtual ~SelLdrLauncherBase();
74 :
75 : /////////////////////////////////////////////////////////////////////////////
76 : // Browser start-up: (used by the plugin inside or outside of Chrome build.)
77 : /////////////////////////////////////////////////////////////////////////////
78 :
79 : virtual bool Start(const char* url) = 0;
80 :
81 : /////////////////////////////////////////////////////////////////////////////
82 : // After starting the sel_ldr process.
83 : /////////////////////////////////////////////////////////////////////////////
84 :
85 : // Connects bootstrap socket.
86 : bool ConnectBootstrapSocket();
87 :
88 : // Retrieves the socket address.
89 : bool RetrieveSockAddr();
90 :
91 : // Sets up the command channel |command|.
92 : bool SetupCommand(NaClSrpcChannel* command);
93 :
94 : // Load |nexe| over the command channel |command|.
95 : bool LoadModule(NaClSrpcChannel* command, DescWrapper* nexe);
96 :
97 : // Sets up the command channel |command| and sends the SRPC to load |nexe|.
98 : bool SetupCommandAndLoad(NaClSrpcChannel* command, DescWrapper* nexe);
99 :
100 : // Sends the SRPC to start the nexe over |command|.
101 : bool StartModule(NaClSrpcChannel* command);
102 :
103 : // Sets up the SRPC channel |out_app_chan|.
104 : bool SetupAppChannel(NaClSrpcChannel* out_app_chan);
105 :
106 : // Sends the SRPC to start the nexe over |command| and sets up the application
107 : // SRPC chanel |out_app_chan|.
108 : bool StartModuleAndSetupAppChannel(NaClSrpcChannel* command,
109 : NaClSrpcChannel* out_app_chan);
110 :
111 : // Returns the socket address used to connect to the sel_ldr.
112 2 : DescWrapper* secure_socket_addr() const { return secure_socket_addr_.get(); }
113 :
114 : // Returns the socket address used to connect to the module.
115 15 : DescWrapper* socket_addr() const { return socket_addr_.get(); }
116 :
117 : // Wraps a raw NaClDesc descriptor. If NULL is returned, caller retains
118 : // ownership of the reference.
119 : DescWrapper* Wrap(NaClDesc* raw_desc);
120 :
121 : // As above, but raw_desc is Unref'd on failure.
122 : DescWrapper* WrapCleanup(NaClDesc* raw_desc);
123 :
124 : // Get post-crash NaClLog data. This include some recent NaClLog
125 : // output as well as the LOG_FATAL message. In the case of a severe
126 : // crash -- or if the peer sel_ldr does not support NaClLog crash
127 : // logging -- this may return the empty string.
128 : //
129 : // NB: If the NaCl module has not exited or crashed, this call will
130 : // block.
131 : nacl::string GetCrashLogOutput();
132 :
133 : protected:
134 : NaClHandle channel_;
135 :
136 : private:
137 : // lifetime of bootstrap_socket_ must be at least that of factory_
138 : scoped_ptr<DescWrapperFactory> factory_;
139 : scoped_ptr<DescWrapper> bootstrap_socket_;
140 : // The socket address returned from sel_ldr for connects.
141 : scoped_ptr<DescWrapper> secure_socket_addr_;
142 : scoped_ptr<DescWrapper> socket_addr_;
143 : };
144 :
145 : class SelLdrLauncherStandalone : public SelLdrLauncherBase {
146 : public:
147 : SelLdrLauncherStandalone();
148 : virtual ~SelLdrLauncherStandalone();
149 :
150 : virtual bool Start(const char* url);
151 :
152 : /////////////////////////////////////////////////////////////////////////////
153 : // Command line start-up: (Only used by sel_universal.)
154 : //
155 : // The command line must include a file path for the nexe application or an
156 : // indicator that a reference will be supplied after the launch over RPC.
157 : /////////////////////////////////////////////////////////////////////////////
158 :
159 : // Starts a sel_ldr process. If |prefix| is not empty, adds prefix arguments,
160 : // like using 'time', to run the sel_ldr within. This is primarily intended
161 : // to provide a hook for qemu emulation or for timing. |sel_ldr_argv|
162 : // specifies the arguments to be passed to sel_ldr itself, while
163 : // |application_argv| specifies the arguments to be passed to the nexe.
164 : // If subprocess creation fails, returns false and both child_process_ and
165 : // channel_ are set to NACL_INVALID_HANDLE.
166 : virtual bool StartViaCommandLine(
167 : const std::vector<nacl::string>& prefix,
168 : const std::vector<nacl::string>& sel_ldr_argv,
169 : const std::vector<nacl::string>& application_argv);
170 :
171 : // Returns the child process handle.
172 0 : NaClHandle child_process() const { return child_process_; }
173 :
174 : protected:
175 : // On Windows, child_process_ is a handle for the process. On Unix,
176 : // child_process_ is a process ID.
177 : NaClHandle child_process_;
178 :
179 : private:
180 : // Builds a command line out of the prepopulated args.
181 : void BuildCommandLine(std::vector<nacl::string>* command);
182 :
183 : // Sets up the command line to start a sel_ldr. |prefix| specifies the
184 : // set of prefixes to apply to the sel_ldr invocation (e.g., 'time' or
185 : // 'qemu'). |sel_ldr_argv| specifies the arguments to be passed to sel_ldr
186 : // itself, while |application_argv| specifies the arguments to be passed to
187 : // the nexe.
188 : void InitCommandLine(const std::vector<nacl::string>& prefix,
189 : const std::vector<nacl::string>& sel_ldr_argv,
190 : const std::vector<nacl::string>& app_argv);
191 :
192 : // Creates a socket pair. Dups the first socket into the NaCl subprocess as
193 : // dest_fd. Returns the second socket or NACL_INVALID_HANDLE on failure.
194 : NaClHandle CreateBootstrapSocket(nacl::string* dest_fd);
195 :
196 : void GetPluginDirectory(char* buffer, size_t len);
197 : nacl::string GetSelLdrPathName();
198 : nacl::string GetSelLdrBootstrapPathName();
199 : void CloseHandlesAfterLaunch();
200 :
201 : // Kill the child process. The channel() remains valid, but nobody
202 : // is talking on the other end. Returns true if successful.
203 : bool KillChildProcess();
204 :
205 : // The following members are used to initialize and build the command line.
206 : // The detailed magic is in BuildCommandLine() but roughly we run
207 : // <prefix> <sel_ldr> <extra stuff> <sel_ldr_argv> -- <nexe_args>
208 : // Prefix parameters or empty if not used.
209 : std::vector<nacl::string> command_prefix_;
210 : // Path to the sel_ldr chain loader executable.
211 : nacl::string sel_ldr_bootstrap_;
212 : // Path to the sel_ldr executable
213 : nacl::string sel_ldr_;
214 : // arguments to sel_ldr
215 : std::vector<nacl::string> sel_ldr_argv_;
216 : // arguments to the nexe
217 : std::vector<nacl::string> application_argv_;
218 :
219 : std::vector<NaClHandle> close_after_launch_;
220 :
221 : scoped_ptr<SelLdrLocator> sel_ldr_locator_;
222 : };
223 :
224 : } // namespace nacl
225 :
226 : #endif // NATIVE_CLIENT_SRC_TRUSTED_NONNACL_UTIL_SEL_LDR_LAUNCHER_H_
|