| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 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 | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 #include <string.h> | 7 #include <string.h> |
| 8 #include <windows.h> | 8 #include <windows.h> |
| 9 | 9 |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "native_client/src/include/nacl_string.h" | 12 #include "native_client/src/include/nacl_string.h" |
| 13 #include "native_client/src/include/portability.h" | 13 #include "native_client/src/include/portability.h" |
| 14 #include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h" | 14 #include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h" |
| 15 #include "native_client/src/trusted/desc/nacl_desc_base.h" | 15 #include "native_client/src/trusted/desc/nacl_desc_base.h" |
| 16 | 16 |
| 17 // Use a predefined symbol to get a handle to the current module. | 17 // Use a predefined symbol to get a handle to the current module. |
| 18 // http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx | 18 // http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx |
| 19 // @IGNORE_LINES_FOR_CODE_HYGIENE[1] | 19 // @IGNORE_LINES_FOR_CODE_HYGIENE[1] |
| 20 extern "C" IMAGE_DOS_HEADER __ImageBase; | 20 extern "C" IMAGE_DOS_HEADER __ImageBase; |
| 21 | 21 |
| 22 using std::vector; | 22 using std::vector; |
| 23 | 23 |
| 24 namespace nacl { | 24 namespace nacl { |
| 25 | 25 |
| 26 SelLdrLauncher::~SelLdrLauncher() { | 26 SelLdrLauncherStandalone::~SelLdrLauncherStandalone() { |
| 27 CloseHandlesAfterLaunch(); | 27 CloseHandlesAfterLaunch(); |
| 28 #if defined(NACL_STANDALONE) | |
| 29 if (kInvalidHandle != child_process_) { | 28 if (kInvalidHandle != child_process_) { |
| 30 // Ensure child process (service runtime) is kaput. NB: we might | 29 // Ensure child process (service runtime) is kaput. NB: we might |
| 31 // close the command channel (or use the hard_shutdown RPC) rather | 30 // close the command channel (or use the hard_shutdown RPC) rather |
| 32 // than killing the process to allow the service runtime to do | 31 // than killing the process to allow the service runtime to do |
| 33 // clean up, but the plugin should be responsible for that and we | 32 // clean up, but the plugin should be responsible for that and we |
| 34 // shouldn't introduce any timeout wait in a dtor. Currently, | 33 // shouldn't introduce any timeout wait in a dtor. Currently, |
| 35 // ServiceRuntime::Shutdown kills the subprocess before closing | 34 // ServiceRuntime::Shutdown kills the subprocess before closing |
| 36 // the command channel, so we aren't providing the opportunity for | 35 // the command channel, so we aren't providing the opportunity for |
| 37 // a more graceful shutdown. | 36 // a more graceful shutdown. |
| 38 KillChildProcess(); | 37 KillChildProcess(); |
| 39 CloseHandle(child_process_); | 38 CloseHandle(child_process_); |
| 40 } | 39 } |
| 41 #endif | |
| 42 if (kInvalidHandle != channel_) { | |
| 43 Close(channel_); | |
| 44 } | |
| 45 } | 40 } |
| 46 | 41 |
| 47 nacl::string SelLdrLauncher::GetSelLdrPathName() { | 42 nacl::string SelLdrLauncherStandalone::GetSelLdrPathName() { |
| 48 char buffer[FILENAME_MAX]; | 43 char buffer[FILENAME_MAX]; |
| 49 // Currently only the Chrome build uses the gyp-generated binaries, and | 44 // Currently only the Chrome build uses the gyp-generated binaries, |
| 50 // Chrome does not start sel_ldr by means of SelLdrLauncher. So we only | 45 // and Chrome does not start sel_ldr by means of |
| 51 // refer to sel_ldr.exe here. | 46 // SelLdrLauncherStandalone. So we only refer to sel_ldr.exe here. |
| 52 const char* const kSelLdrBasename = "\\sel_ldr.exe"; | 47 const char* const kSelLdrBasename = "\\sel_ldr.exe"; |
| 53 GetPluginDirectory(buffer, sizeof(buffer)); | 48 GetPluginDirectory(buffer, sizeof(buffer)); |
| 54 return nacl::string(buffer) + kSelLdrBasename; | 49 return nacl::string(buffer) + kSelLdrBasename; |
| 55 } | 50 } |
| 56 | 51 |
| 57 nacl::string SelLdrLauncher::GetSelLdrBootstrapPathName() { | 52 nacl::string SelLdrLauncherStandalone::GetSelLdrBootstrapPathName() { |
| 58 return nacl::string(NACL_NO_FILE_PATH); | 53 return nacl::string(NACL_NO_FILE_PATH); |
| 59 } | 54 } |
| 60 | 55 |
| 61 // TODO(sehr): document what this is supposed to do exactly | 56 // TODO(sehr): document what this is supposed to do exactly |
| 62 // NOTE: this may be buggy, e.g. how is \\ handled? | 57 // NOTE: this may be buggy, e.g. how is \\ handled? |
| 63 static nacl::string Escape(nacl::string s) { | 58 static nacl::string Escape(nacl::string s) { |
| 64 nacl::string result; | 59 nacl::string result; |
| 65 for (size_t i = 0; i < s.size(); ++i) { | 60 for (size_t i = 0; i < s.size(); ++i) { |
| 66 if (s[i] == '"') { | 61 if (s[i] == '"') { |
| 67 result += "\\\""; | 62 result += "\\\""; |
| 68 } else if (s[i] == '\\' && i + 1 < s.size() && s[i + 1] == '"') { | 63 } else if (s[i] == '\\' && i + 1 < s.size() && s[i + 1] == '"') { |
| 69 result += "\\\\\\\""; | 64 result += "\\\\\\\""; |
| 70 ++i; | 65 ++i; |
| 71 } else { | 66 } else { |
| 72 result.push_back(s[i]); | 67 result.push_back(s[i]); |
| 73 } | 68 } |
| 74 } | 69 } |
| 75 | 70 |
| 76 return result; | 71 return result; |
| 77 } | 72 } |
| 78 | 73 |
| 79 Handle SelLdrLauncher::CreateBootstrapSocket(nacl::string* dest_fd) { | 74 Handle SelLdrLauncherStandalone::CreateBootstrapSocket(nacl::string* dest_fd) { |
| 80 Handle pair[2]; | 75 Handle pair[2]; |
| 81 if (SocketPair(pair) == -1) { | 76 if (SocketPair(pair) == -1) { |
| 82 return kInvalidHandle; | 77 return kInvalidHandle; |
| 83 } | 78 } |
| 84 | 79 |
| 85 // Transfer pair[1] to child_process_ by inheritance. | 80 // Transfer pair[1] to child_process_ by inheritance. |
| 86 // TODO(mseaborn): We could probably use SetHandleInformation() to | 81 // TODO(mseaborn): We could probably use SetHandleInformation() to |
| 87 // set HANDLE_FLAG_INHERIT rather than duplicating the handle and | 82 // set HANDLE_FLAG_INHERIT rather than duplicating the handle and |
| 88 // closing the original. But for now, we do the same as in | 83 // closing the original. But for now, we do the same as in |
| 89 // LaunchFromCommandLine() below. | 84 // LaunchFromCommandLine() below. |
| 90 Handle channel; | 85 Handle channel; |
| 91 if (!DuplicateHandle(GetCurrentProcess(), pair[1], | 86 if (!DuplicateHandle(GetCurrentProcess(), pair[1], |
| 92 GetCurrentProcess(), &channel, | 87 GetCurrentProcess(), &channel, |
| 93 0, TRUE, DUPLICATE_SAME_ACCESS)) { | 88 0, TRUE, DUPLICATE_SAME_ACCESS)) { |
| 94 Close(pair[0]); | 89 Close(pair[0]); |
| 95 Close(pair[1]); | 90 Close(pair[1]); |
| 96 return kInvalidHandle; | 91 return kInvalidHandle; |
| 97 } | 92 } |
| 98 Close(pair[1]); | 93 Close(pair[1]); |
| 99 close_after_launch_.push_back(channel); | 94 close_after_launch_.push_back(channel); |
| 100 | 95 |
| 101 *dest_fd = ToString(reinterpret_cast<uintptr_t>(channel)); | 96 *dest_fd = ToString(reinterpret_cast<uintptr_t>(channel)); |
| 102 return pair[0]; | 97 return pair[0]; |
| 103 } | 98 } |
| 104 | 99 |
| 105 #if defined(NACL_STANDALONE) | 100 bool SelLdrLauncherStandalone::StartViaCommandLine( |
| 106 bool SelLdrLauncher::StartViaCommandLine( | |
| 107 const vector<nacl::string>& prefix, | 101 const vector<nacl::string>& prefix, |
| 108 const vector<nacl::string>& sel_ldr_argv, | 102 const vector<nacl::string>& sel_ldr_argv, |
| 109 const vector<nacl::string>& app_argv) { | 103 const vector<nacl::string>& app_argv) { |
| 110 // Set up the command line. | 104 // Set up the command line. |
| 111 InitCommandLine(prefix, sel_ldr_argv, app_argv); | 105 InitCommandLine(prefix, sel_ldr_argv, app_argv); |
| 112 STARTUPINFOA startup_info; | 106 STARTUPINFOA startup_info; |
| 113 PROCESS_INFORMATION process_infomation; | 107 PROCESS_INFORMATION process_infomation; |
| 114 | 108 |
| 115 vector<nacl::string> command; | 109 vector<nacl::string> command; |
| 116 BuildCommandLine(&command); | 110 BuildCommandLine(&command); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 134 &startup_info, | 128 &startup_info, |
| 135 &process_infomation)) { | 129 &process_infomation)) { |
| 136 return false; | 130 return false; |
| 137 } | 131 } |
| 138 | 132 |
| 139 CloseHandlesAfterLaunch(); | 133 CloseHandlesAfterLaunch(); |
| 140 CloseHandle(process_infomation.hThread); | 134 CloseHandle(process_infomation.hThread); |
| 141 child_process_ = process_infomation.hProcess; | 135 child_process_ = process_infomation.hProcess; |
| 142 return true; | 136 return true; |
| 143 } | 137 } |
| 144 #endif | |
| 145 | 138 |
| 146 bool SelLdrLauncher::KillChildProcess() { | 139 bool SelLdrLauncherStandalone::KillChildProcess() { |
| 147 #if defined(NACL_STANDALONE) | |
| 148 if (kInvalidHandle == child_process_) | 140 if (kInvalidHandle == child_process_) |
| 149 return false; | 141 return false; |
| 150 return 0 != TerminateProcess(child_process_, 9); | 142 return 0 != TerminateProcess(child_process_, 9); |
| 151 // 9 is the exit code for the child_process_. The value is actually not | 143 // 9 is the exit code for the child_process_. The value is actually not |
| 152 // material, since (currently) the launcher does not collect/report it. | 144 // material, since (currently) the launcher does not collect/report it. |
| 153 #else | |
| 154 return false; | |
| 155 #endif | |
| 156 } | 145 } |
| 157 | 146 |
| 158 void PluginSelLdrLocator::GetDirectory(char* buffer, size_t len) { | 147 void PluginSelLdrLocator::GetDirectory(char* buffer, size_t len) { |
| 159 // __ImageBase is in the current module, which could be a .dll or .exe | 148 // __ImageBase is in the current module, which could be a .dll or .exe |
| 160 HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase); | 149 HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase); |
| 161 // NOTE: casting down to DWORD is safe the integer will become smaller | 150 // NOTE: casting down to DWORD is safe the integer will become smaller |
| 162 // at worst | 151 // at worst |
| 163 GetModuleFileNameA(this_module, buffer, static_cast<DWORD>(len)); | 152 GetModuleFileNameA(this_module, buffer, static_cast<DWORD>(len)); |
| 164 char* path_end = strrchr(buffer, '\\'); | 153 char* path_end = strrchr(buffer, '\\'); |
| 165 if (NULL != path_end) { | 154 if (NULL != path_end) { |
| 166 *path_end = '\0'; | 155 *path_end = '\0'; |
| 167 } | 156 } |
| 168 } | 157 } |
| 169 | 158 |
| 170 } // namespace nacl | 159 } // namespace nacl |
| OLD | NEW |