| // Copyright 2024 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <memory> |
| #include <string> |
| #include <utility> |
| |
| #include "base/functional/bind.h" |
| #include "base/logging.h" |
| #include "base/no_destructor.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/time/time.h" |
| #include "base/win/access_control_list.h" |
| #include "base/win/security_descriptor.h" |
| #include "base/win/sid.h" |
| #include "remoting/base/crash/breakpad_utils.h" |
| #include "remoting/base/crash/crash_reporting_breakpad.h" |
| #include "remoting/base/logging.h" |
| #include "remoting/base/version.h" |
| #include "third_party/breakpad/breakpad/src/client/windows/crash_generation/crash_generation_server.h" |
| |
| namespace remoting { |
| |
| namespace { |
| |
| using base::win::SecurityDescriptor; |
| using base::win::Sid; |
| using base::win::SecurityAccessMode::kGrant; |
| using base::win::WellKnownSid::kLocalSystem; |
| |
| // Passed as a flag in the named pipe DACL entry to indicate no inheritance. |
| constexpr bool kNoInheritance = false; |
| |
| class BreakpadServer { |
| public: |
| BreakpadServer(); |
| |
| BreakpadServer(const BreakpadServer&) = delete; |
| BreakpadServer& operator=(const BreakpadServer&) = delete; |
| |
| ~BreakpadServer(); |
| |
| static BreakpadServer& GetInstance(); |
| |
| void set_client_connected_time(base::Time client_connected_time) { |
| client_connected_time_ = client_connected_time; |
| } |
| base::Time get_client_connected_time() { return client_connected_time_; } |
| |
| private: |
| base::Time client_connected_time_; |
| std::unique_ptr<google_breakpad::CrashGenerationServer> crash_server_; |
| }; |
| |
| void OnClientConnectedCallback(void* context, |
| const google_breakpad::ClientInfo* client_info) { |
| HOST_LOG << "OOP Crash client connected"; |
| BreakpadServer::GetInstance().set_client_connected_time( |
| base::Time::NowFromSystemTime()); |
| } |
| |
| void OnClientDumpRequestCallback(void* context, |
| const google_breakpad::ClientInfo* client_info, |
| const std::wstring* file_path) { |
| if (!file_path) { |
| LOG(ERROR) << "OnClientDumpRequestCallback called with invalid file_path"; |
| return; |
| } |
| base::FilePath dump_file(*file_path); |
| if (!GetMinidumpDirectoryPath().IsParent(dump_file)) { |
| LOG(ERROR) << "Minidump written to an unexpected location: " << dump_file; |
| return; |
| } |
| |
| base::Value::Dict metadata; |
| // Use the crash server version since we update all host components in the |
| // same package and we've seen problems trying to use the metadata provided |
| // by the client process, see crbug.com/350725178. |
| metadata.Set(kBreakpadProductVersionKey, REMOTING_VERSION_STRING); |
| |
| // We only have one OOP client so we can use the value of the 'last connected' |
| // client to determine an approximate uptime for that process. |
| auto process_start_time = |
| BreakpadServer::GetInstance().get_client_connected_time(); |
| auto process_uptime = base::Time::NowFromSystemTime() - process_start_time; |
| metadata.Set(kBreakpadProcessUptimeKey, |
| base::NumberToString(process_uptime.InMilliseconds())); |
| |
| WriteMetadataForMinidump(dump_file, std::move(metadata)); |
| } |
| |
| BreakpadServer::BreakpadServer() { |
| base::win::SecurityDescriptor sd; |
| sd.set_owner(Sid(kLocalSystem)); |
| sd.set_group(Sid(kLocalSystem)); |
| |
| // Configure the named pipe to prevent non-SYSTEM access unless a handle is |
| // created by the server and provided over IPC or STDIO. |
| if (!sd.SetDaclEntry(kLocalSystem, kGrant, FILE_ALL_ACCESS, kNoInheritance)) { |
| LOG(ERROR) << "Failed to set named pipe security attributes, skipping " |
| << "out-of-process crash handler initialization."; |
| return; |
| } |
| |
| SECURITY_DESCRIPTOR security_descriptor = sd.ToAbsolute(); |
| |
| SECURITY_ATTRIBUTES security_attributes = {0}; |
| security_attributes.nLength = sizeof(security_attributes); |
| security_attributes.lpSecurityDescriptor = &security_descriptor; |
| security_attributes.bInheritHandle = false; |
| |
| crash_server_ = std::make_unique<google_breakpad::CrashGenerationServer>( |
| kCrashServerPipeName, &security_attributes, |
| /*connect_callback=*/OnClientConnectedCallback, |
| /*connect_context=*/nullptr, |
| /*dump_callback=*/OnClientDumpRequestCallback, |
| /*dump_context=*/nullptr, |
| /*exit_callback=*/nullptr, |
| /*exit_context=*/nullptr, |
| /*upload_request_callback=*/nullptr, |
| /*upload_context=*/nullptr, |
| /*generate_dumps=*/true, &GetMinidumpDirectoryPath().value()); |
| crash_server_->Start(); |
| } |
| |
| BreakpadServer::~BreakpadServer() = default; |
| |
| // static |
| BreakpadServer& BreakpadServer::GetInstance() { |
| static base::NoDestructor<BreakpadServer> instance; |
| return *instance; |
| } |
| |
| } // namespace |
| |
| void InitializeOopCrashServer() { |
| // Touch the object to make sure it is initialized. |
| BreakpadServer::GetInstance(); |
| } |
| |
| } // namespace remoting |