1 : /*
2 : * Copyright (c) 2011 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 :
8 : // Utility class for launching sel_ldr.
9 :
10 : #ifndef NATIVE_CLIENT_SRC_TRUSTED_NONNACL_UTIL_SEL_LDR_LAUNCHER_H_
11 : #define NATIVE_CLIENT_SRC_TRUSTED_NONNACL_UTIL_SEL_LDR_LAUNCHER_H_
12 :
13 : #include <vector>
14 :
15 : #include "native_client/src/include/nacl_scoped_ptr.h"
16 : #include "native_client/src/include/nacl_string.h"
17 : #include "native_client/src/include/portability.h"
18 : #include "native_client/src/shared/imc/nacl_imc.h"
19 : #include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
20 : #include "native_client/src/trusted/service_runtime/nacl_error_code.h"
21 :
22 : struct NaClSrpcChannel;
23 : struct NaClDesc;
24 :
25 : namespace nacl {
26 : // TODO(robertm): Move this to new header if it becomes more popular.
27 22 : template <class T> nacl::string ToString(const T& t) {
28 22 : nacl::stringstream ss;
29 22 : ss << t;
30 22 : return ss.str();
31 : }
32 :
33 : /*
34 : * This class defines an interface that locates sel_ldr.
35 : */
36 : class SelLdrLocator {
37 : public:
38 : // Returns a directory with sel_ldr.
39 : virtual void GetDirectory(char* buffer, size_t len) = 0;
40 :
41 12 : SelLdrLocator() {}
42 :
43 0 : virtual ~SelLdrLocator() {}
44 :
45 : DISALLOW_COPY_AND_ASSIGN(SelLdrLocator);
46 : };
47 :
48 : /*
49 : * Default implementation of SelLdrLocator which tries to
50 : * locate a browser plugin. Default constructor of SelLdrLauncher use it.
51 : */
52 11 : class PluginSelLdrLocator : public SelLdrLocator {
53 : public:
54 : // We have different implementations for all platforms.
55 : virtual void GetDirectory(char* buffer, size_t len);
56 :
57 12 : PluginSelLdrLocator() {}
58 :
59 : DISALLOW_COPY_AND_ASSIGN(PluginSelLdrLocator);
60 : };
61 :
62 : /*
63 : * This class encapsulates the process of launching an instance of sel_ldr
64 : * to communicate with the NaCl plugin over an IMC channel.
65 : *
66 : * The sel_ldr process can be forked directly using a command line of args
67 : * or by sending a message to the (Chrome) browser process.
68 : */
69 : struct SelLdrLauncher {
70 : public:
71 : SelLdrLauncher();
72 :
73 : explicit SelLdrLauncher(SelLdrLocator* sel_ldr_locator);
74 : ~SelLdrLauncher();
75 :
76 : Handle child_process() const { return child_process_; }
77 :
78 : /////////////////////////////////////////////////////////////////////////////
79 : // Command line start-up: (Only used by sel_universal.)
80 : //
81 : // The command line must include a file path for the nexe application or an
82 : // indicator that a reference will be supplied after the launch over RPC.
83 : /////////////////////////////////////////////////////////////////////////////
84 :
85 : // Creates a socket pair. Maps the first socket into the NaCl
86 : // subprocess's FD table as dest_fd. Sets the corresponding command line arg.
87 : // Returns the second socket. Returns kInvalidHandle on failure.
88 : Handle ExportImcFD(int dest_fd);
89 :
90 : // Sets up the command line to start a sel_ldr. Specifies |imc_fd| to
91 : // use for bootstrapping. |sel_ldr_argv| specifies the arguments to be
92 : // passed to sel_ldr itself, while |application_argv| specifies the arguments
93 : // to be passed to the nexe.
94 : void InitCommandLine(int imc_fd,
95 : const std::vector<nacl::string>& sel_ldr_argv,
96 : const std::vector<nacl::string>& application_argv);
97 :
98 : // If subprocess creation fails, both child_process_ and channel_ are set to
99 : // kInvalidHandle. We have different implementations for posix and win.
100 : // You must call InitCommandLine() before calling this function.
101 : bool LaunchFromCommandLine();
102 :
103 : // Builds a command line out of the prepopulated args.
104 : void BuildCommandLine(std::vector<nacl::string>* command);
105 :
106 : // Sets up the command channel |command| and sends the SRPC to load |nexe|.
107 : bool SetupCommandAndLoad(NaClSrpcChannel* command,
108 : DescWrapper* nexe);
109 :
110 : // Sends the SRPC to start the nexe over |command| and sets up the application
111 : // SRPC chanel |out_app_chan|.
112 : bool StartModuleAndSetupAppChannel(NaClSrpcChannel* command,
113 : NaClSrpcChannel* out_app_chan);
114 :
115 : // Add a prefix shell program, like 'time', to run the sel_ldr in
116 : // This is primarily intended to provide a hook for qemu emulation
117 : void SetCommandPrefix(const nacl::string& prefix);
118 :
119 : // Kill the child process. The channel() remains valid, but nobody
120 : // is talking on the other end. Returns true if successful.
121 : bool KillChildProcess();
122 :
123 : // User is responsible for invoking channel() and then taking
124 : // ownership of the handle prior to the Dtor firing.
125 : Handle channel() const { return channel_; }
126 :
127 : // Returns the socket address used to connect to the sel_ldr.
128 10 : DescWrapper* socket_addr() const { return socket_addr_.get(); }
129 :
130 : // Wraps a raw NaClDesc descriptor. If NULL is returned, caller retains
131 : // ownership of the reference.
132 : DescWrapper* Wrap(NaClDesc* raw_desc);
133 :
134 : // As above, but raw_desc is Unref'd on failure.
135 : DescWrapper* WrapCleanup(NaClDesc* raw_desc);
136 :
137 : /////////////////////////////////////////////////////////////////////////////
138 : // Start the sel_ldr process. No nexe information is passed at this point.
139 : // It will be supplied over RPC after start-up.
140 : /////////////////////////////////////////////////////////////////////////////
141 :
142 : bool Start(int socket_count, Handle* result_sockets);
143 :
144 : private:
145 : // OpenSrpcChannels is essentially the following sequence of
146 : // (lower-level) operations.
147 :
148 : // BEGIN EQUIVALENT SEQUENCE
149 :
150 : bool SetupBootstrapChannel();
151 : bool GetLdrSocketAddress();
152 : bool SetupCommandChannel(NaClSrpcChannel* command);
153 :
154 : // LoadModule supplies, via the |command| channel, the |nexe| file
155 : // for the service runtime to load.
156 : bool LoadModule(NaClSrpcChannel* command, DescWrapper* nexe);
157 :
158 : // ----
159 :
160 : // Tell the service runtime to start the NaCl module via the
161 : // |command| channel. If |error| is non-NULL, any failures will
162 : // cause the error code to be written there.
163 : bool StartModule(NaClSrpcChannel* command, NaClErrorCode* error);
164 :
165 : bool SetupApplicationChannel(NaClSrpcChannel* app_channel);
166 :
167 : // END EQUIVALENT SEQUENCE
168 :
169 : void GetPluginDirectory(char* buffer, size_t len);
170 : nacl::string GetSelLdrPathName();
171 : nacl::string GetSelLdrBootstrapPathName();
172 : void CloseHandlesAfterLaunch();
173 :
174 : Handle child_process_;
175 : Handle channel_;
176 : int channel_number_; // IMC file descriptor.
177 :
178 : // The following members are used to initialize and build the command line.
179 : // The detailed magic is in BuildCommandLine() but roughly we run
180 : // <prefix> <sel_ldr> <extra stuff> -f <nexe> <sel_ldr_argv> -- <nexe_args>
181 : // Path to prefix tool or empty if not used
182 : nacl::string command_prefix_;
183 : nacl::string sel_ldr_bootstrap_;
184 : // Path to the sel_ldr executable
185 : nacl::string sel_ldr_;
186 : // arguments to sel_ldr
187 : std::vector<nacl::string> sel_ldr_argv_;
188 : // arguments to the nexe
189 : std::vector<nacl::string> application_argv_;
190 :
191 : std::vector<Handle> close_after_launch_;
192 :
193 : // lifetime of bootstrap_socket_ must be at least that of factory_
194 : scoped_ptr<DescWrapperFactory> factory_;
195 : scoped_ptr<DescWrapper> bootstrap_socket_;
196 : // The socket address returned from sel_ldr for connects.
197 : scoped_ptr<DescWrapper> socket_addr_;
198 : scoped_ptr<SelLdrLocator> sel_ldr_locator_;
199 : };
200 :
201 : } // namespace nacl
202 :
203 : #endif // NATIVE_CLIENT_SRC_TRUSTED_NONNACL_UTIL_SEL_LDR_LAUNCHER_H_
|