// Copyright 2019 The Crashpad Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "handler/linux/capture_snapshot.h" #include #include "snapshot/crashpad_info_client_options.h" #include "snapshot/sanitized/sanitization_information.h" #include "util/misc/metrics.h" #include "util/misc/tri_state.h" namespace crashpad { bool CaptureSnapshot( PtraceConnection* connection, const ExceptionHandlerProtocol::ClientInformation& info, const std::map& process_annotations, uid_t client_uid, VMAddress requesting_thread_stack_address, pid_t* requesting_thread_id, std::unique_ptr* snapshot, std::unique_ptr* sanitized_snapshot) { std::unique_ptr process_snapshot( new ProcessSnapshotLinux()); if (!process_snapshot->Initialize(connection)) { Metrics::ExceptionCaptureResult(Metrics::CaptureResult::kSnapshotFailed); return false; } pid_t local_requesting_thread_id = -1; if (requesting_thread_stack_address) { local_requesting_thread_id = process_snapshot->FindThreadWithStackAddress( requesting_thread_stack_address); } if (requesting_thread_id) { *requesting_thread_id = local_requesting_thread_id; } if (!process_snapshot->InitializeException(info.exception_information_address, local_requesting_thread_id)) { Metrics::ExceptionCaptureResult( Metrics::CaptureResult::kExceptionInitializationFailed); return false; } Metrics::ExceptionCode(process_snapshot->Exception()->Exception()); CrashpadInfoClientOptions client_options; process_snapshot->GetCrashpadOptions(&client_options); if (client_options.crashpad_handler_behavior == TriState::kDisabled) { return false; } for (auto& p : process_annotations) { process_snapshot->AddAnnotation(p.first, p.second); } if (info.sanitization_information_address) { SanitizationInformation sanitization_info; ProcessMemoryRange range; if (!range.Initialize(connection->Memory(), connection->Is64Bit()) || !range.Read(info.sanitization_information_address, sizeof(sanitization_info), &sanitization_info)) { Metrics::ExceptionCaptureResult( Metrics::CaptureResult::kSanitizationInitializationFailed); return false; } auto allowed_annotations = std::make_unique>(); auto allowed_memory_ranges = std::make_unique>>(); if (!ReadAllowedAnnotations(range, sanitization_info.allowed_annotations_address, allowed_annotations.get()) || !ReadAllowedMemoryRanges( range, sanitization_info.allowed_memory_ranges_address, allowed_memory_ranges.get())) { Metrics::ExceptionCaptureResult( Metrics::CaptureResult::kSanitizationInitializationFailed); return false; } std::unique_ptr sanitized( new ProcessSnapshotSanitized()); if (!sanitized->Initialize(process_snapshot.get(), sanitization_info.allowed_annotations_address ? std::move(allowed_annotations) : nullptr, std::move(allowed_memory_ranges), sanitization_info.target_module_address, sanitization_info.sanitize_stacks)) { Metrics::ExceptionCaptureResult( Metrics::CaptureResult::kSkippedDueToSanitization); return false; } *sanitized_snapshot = std::move(sanitized); } *snapshot = std::move(process_snapshot); return true; } } // namespace crashpad