// Copyright 2021 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 "util/ios/ios_intermediate_dump_writer.h" #include #include #include "base/posix/eintr_wrapper.h" #include "build/build_config.h" #include "util/ios/raw_logging.h" #include "util/ios/scoped_vm_read.h" namespace crashpad { namespace internal { // Similar to LoggingWriteFile but with CRASHPAD_RAW_LOG. bool RawLoggingWriteFile(int fd, const void* buffer, size_t size) { uintptr_t buffer_int = reinterpret_cast(buffer); while (size > 0) { ssize_t bytes_written = HANDLE_EINTR( write(fd, reinterpret_cast(buffer_int), size)); if (bytes_written < 0 || bytes_written == 0) { CRASHPAD_RAW_LOG_ERROR(bytes_written, "RawLoggingWriteFile"); return false; } buffer_int += bytes_written; size -= bytes_written; } return true; } // Similar to LoggingCloseFile but with CRASHPAD_RAW_LOG. bool RawLoggingCloseFile(int fd) { int rv = IGNORE_EINTR(close(fd)); if (rv != 0) { CRASHPAD_RAW_LOG_ERROR(rv, "RawLoggingCloseFile"); } return rv == 0; } // Similar to LoggingLockFile but with CRASHPAD_RAW_LOG. bool RawLoggingLockFileExclusiveNonBlocking(int fd) { int rv = HANDLE_EINTR(flock(fd, LOCK_EX | LOCK_NB)); if (rv != 0) { CRASHPAD_RAW_LOG_ERROR(rv, "RawLoggingLockFileExclusiveNonBlocking"); } return rv == 0; } bool IOSIntermediateDumpWriter::Open(const base::FilePath& path) { // Set data protection class D (No protection). A file with this type of // protection can be read from or written to at any time. // See: // https://support.apple.com/guide/security/data-protection-classes-secb010e978a/web constexpr int PROTECTION_CLASS_D = 4; fd_ = HANDLE_EINTR(open_dprotected_np(path.value().c_str(), O_WRONLY | O_CREAT | O_TRUNC, PROTECTION_CLASS_D, 0 /* dpflags */, 0644 /* mode */)); if (fd_ < 0) { CRASHPAD_RAW_LOG_ERROR(fd_, "open intermediate dump"); CRASHPAD_RAW_LOG(path.value().c_str()); return false; } return RawLoggingLockFileExclusiveNonBlocking(fd_); } bool IOSIntermediateDumpWriter::Close() { return RawLoggingCloseFile(fd_); } bool IOSIntermediateDumpWriter::ArrayMapStart() { const CommandType command_type = CommandType::kMapStart; return RawLoggingWriteFile(fd_, &command_type, sizeof(command_type)); } bool IOSIntermediateDumpWriter::MapStart(IntermediateDumpKey key) { const CommandType command_type = CommandType::kMapStart; return RawLoggingWriteFile(fd_, &command_type, sizeof(command_type)) && RawLoggingWriteFile(fd_, &key, sizeof(key)); } bool IOSIntermediateDumpWriter::ArrayStart(IntermediateDumpKey key) { const CommandType command_type = CommandType::kArrayStart; return RawLoggingWriteFile(fd_, &command_type, sizeof(command_type)) && RawLoggingWriteFile(fd_, &key, sizeof(key)); } bool IOSIntermediateDumpWriter::MapEnd() { const CommandType command_type = CommandType::kMapEnd; return RawLoggingWriteFile(fd_, &command_type, sizeof(command_type)); } bool IOSIntermediateDumpWriter::ArrayEnd() { const CommandType command_type = CommandType::kArrayEnd; return RawLoggingWriteFile(fd_, &command_type, sizeof(command_type)); } bool IOSIntermediateDumpWriter::RootMapStart() { const CommandType command_type = CommandType::kRootMapStart; return RawLoggingWriteFile(fd_, &command_type, sizeof(command_type)); } bool IOSIntermediateDumpWriter::RootMapEnd() { const CommandType command_type = CommandType::kRootMapEnd; return RawLoggingWriteFile(fd_, &command_type, sizeof(command_type)); } bool IOSIntermediateDumpWriter::AddPropertyInternal(IntermediateDumpKey key, const char* value, size_t value_length) { ScopedVMRead vmread; if (!vmread.Read(value, value_length)) return false; const CommandType command_type = CommandType::kProperty; return RawLoggingWriteFile(fd_, &command_type, sizeof(command_type)) && RawLoggingWriteFile(fd_, &key, sizeof(key)) && RawLoggingWriteFile(fd_, &value_length, sizeof(size_t)) && RawLoggingWriteFile(fd_, vmread.get(), value_length); } } // namespace internal } // namespace crashpad