Chromium Code Reviews| OLD | NEW |
|---|---|
| 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, |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 125 static const auto delete_proc_thread_attribute_list = | 125 static const auto delete_proc_thread_attribute_list = |
| 126 GET_FUNCTION_REQUIRED(L"kernel32.dll", ::DeleteProcThreadAttributeList); | 126 GET_FUNCTION_REQUIRED(L"kernel32.dll", ::DeleteProcThreadAttributeList); |
| 127 delete_proc_thread_attribute_list(proc_thread_attribute_list); | 127 delete_proc_thread_attribute_list(proc_thread_attribute_list); |
| 128 } | 128 } |
| 129 }; | 129 }; |
| 130 | 130 |
| 131 using ScopedProcThreadAttributeList = | 131 using ScopedProcThreadAttributeList = |
| 132 base::ScopedGeneric<PPROC_THREAD_ATTRIBUTE_LIST, | 132 base::ScopedGeneric<PPROC_THREAD_ATTRIBUTE_LIST, |
| 133 ScopedProcThreadAttributeListTraits>; | 133 ScopedProcThreadAttributeListTraits>; |
| 134 | 134 |
| 135 bool IsInheritableHandle(HANDLE handle) { | |
| 136 if (!handle || handle == INVALID_HANDLE_VALUE) | |
| 137 return false; | |
| 138 | |
| 139 // File handles (FILE_TYPE_DISK) and pipe handles (FILE_TYPE_PIPE) are known | |
| 140 // to be inheritable. Console handles (FILE_TYPE_CHAR) are not inheritable via | |
| 141 // PROC_THREAD_ATTRIBUTE_HANDLE_LIST. See | |
| 142 // https://crashpad.chromium.org/bug/77. | |
| 143 DWORD handle_type = GetFileType(handle); | |
| 144 return handle_type == FILE_TYPE_DISK || handle_type == FILE_TYPE_PIPE; | |
| 145 } | |
| 146 | |
| 135 // Adds |handle| to |handle_list| if it appears valid, and is not already in | 147 // Adds |handle| to |handle_list| if it appears valid, and is not already in |
| 136 // |handle_list|. | 148 // |handle_list|. |
| 137 // | 149 // |
| 138 // Invalid handles (including INVALID_HANDLE_VALUE and null handles) cannot be | 150 // Invalid handles (including INVALID_HANDLE_VALUE and null handles) cannot be |
| 139 // added to a PPROC_THREAD_ATTRIBUTE_LIST’s PROC_THREAD_ATTRIBUTE_HANDLE_LIST. | 151 // added to a PPROC_THREAD_ATTRIBUTE_LIST’s PROC_THREAD_ATTRIBUTE_HANDLE_LIST. |
| 140 // If INVALID_HANDLE_VALUE appears, CreateProcess() will fail with | 152 // If INVALID_HANDLE_VALUE appears, CreateProcess() will fail with |
| 141 // ERROR_INVALID_PARAMETER. If a null handle appears, the child process will | 153 // ERROR_INVALID_PARAMETER. If a null handle appears, the child process will |
| 142 // silently not inherit any handles. | 154 // silently not inherit any handles. |
| 143 // | 155 // |
| 144 // Use this function to add handles with uncertain validities. | 156 // Use this function to add handles with uncertain validities. |
| 145 void AddHandleToListIfValid(std::vector<HANDLE>* handle_list, HANDLE handle) { | 157 void AddHandleToListIfValidAndInheritable(std::vector<HANDLE>* handle_list, |
| 158 HANDLE handle) { | |
| 146 // There doesn't seem to be any documentation of this, but if there's a handle | 159 // There doesn't seem to be any documentation of this, but if there's a handle |
| 147 // duplicated in this list, CreateProcess() fails with | 160 // duplicated in this list, CreateProcess() fails with |
| 148 // ERROR_INVALID_PARAMETER. | 161 // ERROR_INVALID_PARAMETER. |
| 149 if (handle && handle != INVALID_HANDLE_VALUE && | 162 if (IsInheritableHandle(handle) && |
| 150 std::find(handle_list->begin(), handle_list->end(), handle) == | 163 std::find(handle_list->begin(), handle_list->end(), handle) == |
| 151 handle_list->end()) { | 164 handle_list->end()) { |
| 152 handle_list->push_back(handle); | 165 handle_list->push_back(handle); |
| 153 } | 166 } |
| 154 } | 167 } |
| 155 | 168 |
| 156 } // namespace | 169 } // namespace |
| 157 | 170 |
| 158 namespace crashpad { | 171 namespace crashpad { |
| 159 | 172 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 211 &command_line); | 224 &command_line); |
| 212 } | 225 } |
| 213 AppendCommandLineArgument( | 226 AppendCommandLineArgument( |
| 214 base::UTF8ToUTF16(base::StringPrintf("--handshake-handle=0x%x", | 227 base::UTF8ToUTF16(base::StringPrintf("--handshake-handle=0x%x", |
| 215 HandleToInt(pipe_write))), | 228 HandleToInt(pipe_write))), |
| 216 &command_line); | 229 &command_line); |
| 217 | 230 |
| 218 DWORD creation_flags; | 231 DWORD creation_flags; |
| 219 STARTUPINFOEX startup_info = {}; | 232 STARTUPINFOEX startup_info = {}; |
| 220 startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES; | 233 startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES; |
| 221 startup_info.StartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); | 234 startup_info.StartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); |
|
Mark Mentovai
2015/11/25 04:58:05
We probably shouldn’t even be setting hStdInput/Ou
scottmg
2015/11/25 18:13:58
They are duplicatable I think. I'm not clear on wh
| |
| 222 startup_info.StartupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); | 235 startup_info.StartupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); |
| 223 startup_info.StartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); | 236 startup_info.StartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); |
| 224 | 237 |
| 225 std::vector<HANDLE> handle_list; | 238 std::vector<HANDLE> handle_list; |
| 226 scoped_ptr<uint8_t[]> proc_thread_attribute_list_storage; | 239 scoped_ptr<uint8_t[]> proc_thread_attribute_list_storage; |
| 227 ScopedProcThreadAttributeList proc_thread_attribute_list_owner; | 240 ScopedProcThreadAttributeList proc_thread_attribute_list_owner; |
| 228 | 241 |
| 229 static const auto initialize_proc_thread_attribute_list = | 242 static const auto initialize_proc_thread_attribute_list = |
| 230 GET_FUNCTION(L"kernel32.dll", ::InitializeProcThreadAttributeList); | 243 GET_FUNCTION(L"kernel32.dll", ::InitializeProcThreadAttributeList); |
| 231 static const auto update_proc_thread_attribute = | 244 static const auto update_proc_thread_attribute = |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 260 rv = initialize_proc_thread_attribute_list( | 273 rv = initialize_proc_thread_attribute_list( |
| 261 startup_info.lpAttributeList, 1, 0, &size); | 274 startup_info.lpAttributeList, 1, 0, &size); |
| 262 if (!rv) { | 275 if (!rv) { |
| 263 PLOG(ERROR) << "InitializeProcThreadAttributeList"; | 276 PLOG(ERROR) << "InitializeProcThreadAttributeList"; |
| 264 return false; | 277 return false; |
| 265 } | 278 } |
| 266 proc_thread_attribute_list_owner.reset(startup_info.lpAttributeList); | 279 proc_thread_attribute_list_owner.reset(startup_info.lpAttributeList); |
| 267 | 280 |
| 268 handle_list.reserve(4); | 281 handle_list.reserve(4); |
| 269 handle_list.push_back(pipe_write); | 282 handle_list.push_back(pipe_write); |
| 270 AddHandleToListIfValid(&handle_list, startup_info.StartupInfo.hStdInput); | 283 AddHandleToListIfValidAndInheritable(&handle_list, |
| 271 AddHandleToListIfValid(&handle_list, startup_info.StartupInfo.hStdOutput); | 284 startup_info.StartupInfo.hStdInput); |
| 272 AddHandleToListIfValid(&handle_list, startup_info.StartupInfo.hStdError); | 285 AddHandleToListIfValidAndInheritable(&handle_list, |
| 286 startup_info.StartupInfo.hStdOutput); | |
| 287 AddHandleToListIfValidAndInheritable(&handle_list, | |
| 288 startup_info.StartupInfo.hStdError); | |
| 273 rv = update_proc_thread_attribute( | 289 rv = update_proc_thread_attribute( |
| 274 startup_info.lpAttributeList, | 290 startup_info.lpAttributeList, |
| 275 0, | 291 0, |
| 276 PROC_THREAD_ATTRIBUTE_HANDLE_LIST, | 292 PROC_THREAD_ATTRIBUTE_HANDLE_LIST, |
| 277 &handle_list[0], | 293 &handle_list[0], |
| 278 handle_list.size() * sizeof(handle_list[0]), | 294 handle_list.size() * sizeof(handle_list[0]), |
| 279 nullptr, | 295 nullptr, |
| 280 nullptr); | 296 nullptr); |
| 281 if (!rv) { | 297 if (!rv) { |
| 282 PLOG(ERROR) << "UpdateProcThreadAttribute"; | 298 PLOG(ERROR) << "UpdateProcThreadAttribute"; |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 441 DWORD wfso_result = WaitForSingleObject(g_non_crash_dump_done, INFINITE); | 457 DWORD wfso_result = WaitForSingleObject(g_non_crash_dump_done, INFINITE); |
| 442 PLOG_IF(ERROR, wfso_result != WAIT_OBJECT_0) << "WaitForSingleObject"; | 458 PLOG_IF(ERROR, wfso_result != WAIT_OBJECT_0) << "WaitForSingleObject"; |
| 443 } | 459 } |
| 444 | 460 |
| 445 // static | 461 // static |
| 446 void CrashpadClient::DumpAndCrash(EXCEPTION_POINTERS* exception_pointers) { | 462 void CrashpadClient::DumpAndCrash(EXCEPTION_POINTERS* exception_pointers) { |
| 447 UnhandledExceptionHandler(exception_pointers); | 463 UnhandledExceptionHandler(exception_pointers); |
| 448 } | 464 } |
| 449 | 465 |
| 450 } // namespace crashpad | 466 } // namespace crashpad |
| OLD | NEW |