1 : /* -*- c++ -*- */
2 : /*
3 : * Copyright (c) 2013 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 : #include "native_client/src/trusted/nonnacl_util/launcher_factory.h"
9 :
10 : #include <vector>
11 :
12 : #include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h"
13 :
14 : #if NACL_LINUX || NACL_OSX
15 : # define NACL_NEED_ZYGOTE 1
16 : #elif NACL_WINDOWS
17 : # define NACL_NEED_ZYGOTE 0
18 : #else
19 : # error "What OS?!?"
20 : #endif
21 :
22 : #include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher_zygote.h"
23 :
24 : namespace nacl {
25 :
26 : using std::vector;
27 :
28 : #if NACL_NEED_ZYGOTE
29 52 : class SelLdrLauncherStandaloneProxy : public SelLdrLauncherStandalone {
30 : public:
31 : explicit SelLdrLauncherStandaloneProxy(Zygote* zygote);
32 :
33 : virtual bool StartViaCommandLine(
34 : const vector<nacl::string>& prefix,
35 : const vector<nacl::string>& sel_ldr_argv,
36 : const vector<nacl::string>& app_argv);
37 : // This version of StartViaCommandLine essentially splits
38 : // SelLdrLauncherStandalone's version in half: we transfer the 3
39 : // arguments to the zygote, where the zygote will create its own
40 : // SelLdrLauncherStandalone object where the process creation
41 : // occurs. Note that InitCommandLine and BuildCommandLine will
42 : // execute in the zygote's copy of the object, and it is in
43 : // InitCommandLine where the CreateBootstrapSocket's dest_fd get
44 : // pushed into the command line being built (preceded with "-X").
45 : // After the zygote's copy of
46 : // SelLdrLauncherStandalone::StartViaCommandLine has executed, the
47 : // channel_ member has the desired communication channel needed to
48 : // get (receive) the command channel and application channel socket
49 : // addresses, and we send this channel_ back in the RPC to forcibly
50 : // stuff into the SelLdrLauncherStandaloneProxy object. Since the
51 : // three argv objects are needed after this, the fact that they
52 : // aren't initialized won't matter. Ditto for close_after_launch_
53 : // etc.
54 : //
55 : // NB: the zygote's copy of SelLdrLauncherStandalone must have its
56 : // child_process_ pid set the NACL_INVALID_HANDLE before being
57 : // dtor'd, since otherwise the newly launched process will
58 : // immediately get killed. The pid is retrieved along with the
59 : // channel from the zygote, and we stuff that into the proxy object
60 : // as well, so that the dtor semantics will work out.
61 : private:
62 : Zygote* zygote_;
63 : };
64 :
65 32 : SelLdrLauncherStandaloneProxy::SelLdrLauncherStandaloneProxy(Zygote* zygote)
66 32 : : zygote_(zygote) {}
67 :
68 : bool SelLdrLauncherStandaloneProxy::StartViaCommandLine(
69 16 : const vector<nacl::string>& prefix,
70 16 : const vector<nacl::string>& sel_ldr_argv,
71 16 : const vector<nacl::string>& app_argv) {
72 16 : NaClHandle bootstrap_channel;
73 16 : int channel_id;
74 16 : int pid;
75 :
76 16 : if (!zygote_->SpawnNaClSubprocess(prefix, sel_ldr_argv, app_argv,
77 : &bootstrap_channel, &channel_id, &pid)) {
78 0 : return false;
79 : }
80 16 : if (!zygote_->ReleaseChannelById(channel_id)) {
81 0 : (void) close(bootstrap_channel);
82 : // On Unix-like OSes, closing the bootstrap channel suffices to
83 : // ensure that the spawned subprocess will exit: the bootstrap
84 : // channel contains the socketaddress socketpair endpoints for
85 : // trusted and untrusted connections, and if the zygote had
86 : // crashed, the last reference to the sockpair endpoints will
87 : // disappear with the close, and the imc_accept would get an EOF.
88 : // On Windows, we may be leaking a process, since the IMC channels
89 : // are implemented with named pipes, and there won't be any EOF
90 : // indication. Since this code should never run unless the zygote
91 : // process crashed and thus is hard to test, we leave this
92 : // commented out.
93 : //
94 : // child_process_ = pid;
95 : // KillChildProcess();
96 0 : return false;
97 : }
98 16 : channel_ = bootstrap_channel;
99 16 : child_process_ = pid;
100 16 : return true;
101 16 : }
102 : #endif
103 :
104 : SelLdrLauncherStandaloneFactory::SelLdrLauncherStandaloneFactory(
105 28 : ZygoteBase* zygote_interface)
106 28 : : zygote_(zygote_interface) {}
107 :
108 13 : SelLdrLauncherStandaloneFactory::~SelLdrLauncherStandaloneFactory() {
109 26 : }
110 :
111 : #if NACL_NEED_ZYGOTE
112 : SelLdrLauncherStandalone* SelLdrLauncherStandaloneFactory::
113 : MakeSelLdrLauncherStandalone() {
114 32 : return new SelLdrLauncherStandaloneProxy(
115 : reinterpret_cast<ZygotePosix *>(zygote_));
116 0 : }
117 : #else
118 : SelLdrLauncherStandalone* SelLdrLauncherStandaloneFactory::
119 : MakeSelLdrLauncherStandalone() {
120 : return new SelLdrLauncherStandalone();
121 : }
122 : #endif
123 :
124 : } // namespace nacl
|