Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: client/crashpad_client_win.cc

Issue 1427273003: win: Make StartHandler() restrict HANDLES inherited by crashpad_handler (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Crashpad Authors. All rights reserved. 1 // Copyright 2015 The Crashpad Authors. All rights reserved.
2 // 2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License. 4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at 5 // You may obtain a copy of the License at
6 // 6 //
7 // http://www.apache.org/licenses/LICENSE-2.0 7 // http://www.apache.org/licenses/LICENSE-2.0
8 // 8 //
9 // Unless required by applicable law or agreed to in writing, software 9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, 10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and 12 // See the License for the specific language governing permissions and
13 // limitations under the License. 13 // limitations under the License.
14 14
15 #include "client/crashpad_client.h" 15 #include "client/crashpad_client.h"
16 16
17 #include <string.h> 17 #include <string.h>
18 #include <windows.h> 18 #include <windows.h>
19 19
20 #include "base/atomicops.h" 20 #include "base/atomicops.h"
21 #include "base/logging.h" 21 #include "base/logging.h"
22 #include "base/memory/scoped_ptr.h"
23 #include "base/scoped_generic.h"
22 #include "base/strings/string16.h" 24 #include "base/strings/string16.h"
23 #include "base/strings/stringprintf.h" 25 #include "base/strings/stringprintf.h"
24 #include "base/strings/utf_string_conversions.h" 26 #include "base/strings/utf_string_conversions.h"
25 #include "base/synchronization/lock.h" 27 #include "base/synchronization/lock.h"
26 #include "util/file/file_io.h" 28 #include "util/file/file_io.h"
27 #include "util/win/command_line.h" 29 #include "util/win/command_line.h"
28 #include "util/win/critical_section_with_debug_info.h" 30 #include "util/win/critical_section_with_debug_info.h"
31 #include "util/win/get_function.h"
29 #include "util/win/handle.h" 32 #include "util/win/handle.h"
30 #include "util/win/registration_protocol_win.h" 33 #include "util/win/registration_protocol_win.h"
31 #include "util/win/scoped_handle.h" 34 #include "util/win/scoped_handle.h"
32 35
33 namespace { 36 namespace {
34 37
35 // This handle is never closed. This is used to signal to the server that a dump 38 // This handle is never closed. This is used to signal to the server that a dump
36 // should be taken in the event of a crash. 39 // should be taken in the event of a crash.
37 HANDLE g_signal_exception = INVALID_HANDLE_VALUE; 40 HANDLE g_signal_exception = INVALID_HANDLE_VALUE;
38 41
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 TerminateProcess(GetCurrentProcess(), kCrashExitCodeNoDump); 106 TerminateProcess(GetCurrentProcess(), kCrashExitCodeNoDump);
104 107
105 return EXCEPTION_CONTINUE_SEARCH; 108 return EXCEPTION_CONTINUE_SEARCH;
106 } 109 }
107 110
108 std::wstring FormatArgumentString(const std::string& name, 111 std::wstring FormatArgumentString(const std::string& name,
109 const std::wstring& value) { 112 const std::wstring& value) {
110 return std::wstring(L"--") + base::UTF8ToUTF16(name) + L"=" + value; 113 return std::wstring(L"--") + base::UTF8ToUTF16(name) + L"=" + value;
111 } 114 }
112 115
116 struct ScopedProcThreadAttributeListTraits {
117 static PPROC_THREAD_ATTRIBUTE_LIST InvalidValue() {
118 return nullptr;
119 }
120
121 static void Free(PPROC_THREAD_ATTRIBUTE_LIST proc_thread_attribute_list) {
122 // This is able to use GET_FUNCTION_REQUIRED() instead of GET_FUNCTION()
123 // because it will only be called if InitializeProcThreadAttributeList() and
124 // UpdateProcThreadAttribute() are present.
125 static const auto delete_proc_thread_attribute_list =
126 GET_FUNCTION_REQUIRED(L"kernel32.dll", ::DeleteProcThreadAttributeList);
127 delete_proc_thread_attribute_list(proc_thread_attribute_list);
128 }
129 };
130
131 using ScopedProcThreadAttributeList =
132 base::ScopedGeneric<PPROC_THREAD_ATTRIBUTE_LIST,
133 ScopedProcThreadAttributeListTraits>;
134
135 // Adds |handle| to |handle_list| if it appears valid.
136 //
137 // Invalid handles (including INVALID_HANDLE_VALUE and null handles) cannot be
138 // added to a PPROC_THREAD_ATTRIBUTE_LIST’s PROC_THREAD_ATTRIBUTE_HANDLE_LIST.
139 // If INVALID_HANDLE_VALUE appears, CreateProcess() will fail with
140 // ERROR_INVALID_PARAMETER. If a null handle appears, the child process will
141 // silently not inherit any handles.
142 //
143 // Use this function to add handles with uncertain validities.
144 void AddHandleToListIfValid(std::vector<HANDLE>* handle_list, HANDLE handle) {
145 if (handle && handle != INVALID_HANDLE_VALUE) {
146 handle_list->push_back(handle);
147 }
148 }
149
113 } // namespace 150 } // namespace
114 151
115 namespace crashpad { 152 namespace crashpad {
116 153
117 CrashpadClient::CrashpadClient() 154 CrashpadClient::CrashpadClient()
118 : ipc_pipe_() { 155 : ipc_pipe_() {
119 } 156 }
120 157
121 CrashpadClient::~CrashpadClient() { 158 CrashpadClient::~CrashpadClient() {
122 } 159 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 AppendCommandLineArgument( 202 AppendCommandLineArgument(
166 FormatArgumentString("annotation", 203 FormatArgumentString("annotation",
167 base::UTF8ToUTF16(kv.first + '=' + kv.second)), 204 base::UTF8ToUTF16(kv.first + '=' + kv.second)),
168 &command_line); 205 &command_line);
169 } 206 }
170 AppendCommandLineArgument( 207 AppendCommandLineArgument(
171 base::UTF8ToUTF16(base::StringPrintf("--handshake-handle=0x%x", 208 base::UTF8ToUTF16(base::StringPrintf("--handshake-handle=0x%x",
172 HandleToInt(pipe_write))), 209 HandleToInt(pipe_write))),
173 &command_line); 210 &command_line);
174 211
175 STARTUPINFO startup_info = {}; 212 DWORD creation_flags;
176 startup_info.cb = sizeof(startup_info); 213 STARTUPINFOEX startup_info = {};
177 startup_info.dwFlags = STARTF_USESTDHANDLES; 214 startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
178 startup_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE); 215 startup_info.StartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
179 startup_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); 216 startup_info.StartupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
180 startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE); 217 startup_info.StartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
218
219 std::vector<HANDLE> handle_list;
220 scoped_ptr<uint8_t[]> proc_thread_attribute_list_storage;
221 ScopedProcThreadAttributeList proc_thread_attribute_list_owner;
222
223 static const auto initialize_proc_thread_attribute_list =
224 GET_FUNCTION(L"kernel32.dll", ::InitializeProcThreadAttributeList);
scottmg 2015/11/06 20:15:02 Probably don't need :: on these?
Mark Mentovai 2015/11/06 21:49:09 scottmg wrote:
scottmg 2015/11/06 21:53:34 OK, that's fine then too.
225 static const auto update_proc_thread_attribute =
226 initialize_proc_thread_attribute_list
227 ? GET_FUNCTION(L"kernel32.dll", ::UpdateProcThreadAttribute)
228 : nullptr;
229 if (!initialize_proc_thread_attribute_list || !update_proc_thread_attribute) {
230 // The OS doesn’t allow handle inheritance to be restricted, so the handler
231 // will inherit every inheritable handle.
232 creation_flags = 0;
233 startup_info.StartupInfo.cb = sizeof(startup_info.StartupInfo);
234 } else {
235 // Restrict handle inheritance to just those needed in the handler.
236
237 creation_flags = EXTENDED_STARTUPINFO_PRESENT;
238 startup_info.StartupInfo.cb = sizeof(startup_info);
239 SIZE_T size;
240 rv = initialize_proc_thread_attribute_list(nullptr, 1, 0, &size);
241 if (rv) {
242 LOG(ERROR) << "InitializeProcThreadAttributeList (size) succeeded, "
243 "expected failure";
244 return false;
245 } else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
246 PLOG(ERROR) << "InitializeProcThreadAttributeList (size)";
247 return false;
248 }
249
250 proc_thread_attribute_list_storage.reset(new uint8_t[size]);
251 startup_info.lpAttributeList =
252 reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(
253 proc_thread_attribute_list_storage.get());
254 rv = initialize_proc_thread_attribute_list(
255 startup_info.lpAttributeList, 1, 0, &size);
256 if (!rv) {
257 PLOG(ERROR) << "InitializeProcThreadAttributeList";
258 return false;
259 }
260 proc_thread_attribute_list_owner.reset(startup_info.lpAttributeList);
261
262 handle_list.reserve(4);
263 handle_list.push_back(pipe_write);
264 AddHandleToListIfValid(&handle_list, startup_info.StartupInfo.hStdInput);
265 AddHandleToListIfValid(&handle_list, startup_info.StartupInfo.hStdOutput);
266 AddHandleToListIfValid(&handle_list, startup_info.StartupInfo.hStdError);
267 rv = update_proc_thread_attribute(
268 startup_info.lpAttributeList,
269 0,
270 PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
271 &handle_list[0],
272 handle_list.size() * sizeof(handle_list[0]),
273 nullptr,
274 nullptr);
275 if (!rv) {
276 PLOG(ERROR) << "UpdateProcThreadAttribute";
277 return false;
278 }
279 }
280
181 PROCESS_INFORMATION process_info; 281 PROCESS_INFORMATION process_info;
182 rv = CreateProcess(handler.value().c_str(), 282 rv = CreateProcess(handler.value().c_str(),
183 &command_line[0], 283 &command_line[0],
184 nullptr, 284 nullptr,
185 nullptr, 285 nullptr,
186 true, 286 true,
187 0, 287 creation_flags,
188 nullptr, 288 nullptr,
189 nullptr, 289 nullptr,
190 &startup_info, 290 &startup_info.StartupInfo,
191 &process_info); 291 &process_info);
192 if (!rv) { 292 if (!rv) {
193 PLOG(ERROR) << "CreateProcess"; 293 PLOG(ERROR) << "CreateProcess";
194 return false; 294 return false;
195 } 295 }
196 296
197 rv = CloseHandle(process_info.hThread); 297 rv = CloseHandle(process_info.hThread);
198 PLOG_IF(WARNING, !rv) << "CloseHandle thread"; 298 PLOG_IF(WARNING, !rv) << "CloseHandle thread";
199 299
200 rv = CloseHandle(process_info.hProcess); 300 rv = CloseHandle(process_info.hProcess);
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 reinterpret_cast<crashpad::WinVMAddress>(&exception_pointers); 429 reinterpret_cast<crashpad::WinVMAddress>(&exception_pointers);
330 430
331 bool set_event_result = !!SetEvent(g_signal_non_crash_dump); 431 bool set_event_result = !!SetEvent(g_signal_non_crash_dump);
332 PLOG_IF(ERROR, !set_event_result) << "SetEvent"; 432 PLOG_IF(ERROR, !set_event_result) << "SetEvent";
333 433
334 DWORD wfso_result = WaitForSingleObject(g_non_crash_dump_done, INFINITE); 434 DWORD wfso_result = WaitForSingleObject(g_non_crash_dump_done, INFINITE);
335 PLOG_IF(ERROR, wfso_result != WAIT_OBJECT_0) << "WaitForSingleObject"; 435 PLOG_IF(ERROR, wfso_result != WAIT_OBJECT_0) << "WaitForSingleObject";
336 } 436 }
337 437
338 } // namespace crashpad 438 } // namespace crashpad
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698