crashpad/util/ios/ios_intermediate_dump_writer.cc
Justin Cohen c367128a85 ios: Don't use POSIX file locks for iOS intermediate dumps.
Instead use a custom mechanism based on the filename. Rather than a
filename of <uuid>, instead name the file <bundle-id>|<uuid>[.locked].
A locked file will have the optional .locked extension. Files can be
unlocked after writing an intermediate dump, or during initialization by
looking for matching bundle-ids.

Clients that call ProcessIntermediateDumps() will clean up any leftover
locked intermediate dumps. Clients that never call
ProcessIntermediateDumps, such as extensions that leave this up to the
main application, will be cleaned up in a followup change.

Bug: crashpad:31
Change-Id: Icd4aaa3b79351870fbe9b8463cfbdf7cff7d5f87
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/3229429
Commit-Queue: Justin Cohen <justincohen@chromium.org>
Reviewed-by: Mark Mentovai <mark@chromium.org>
Reviewed-by: Rohit Rao <rohitrao@chromium.org>
2021-10-19 18:23:51 +00:00

129 lines
4.6 KiB
C++

// 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 <fcntl.h>
#include <unistd.h>
#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<uintptr_t>(buffer);
while (size > 0) {
ssize_t bytes_written = HANDLE_EINTR(
write(fd, reinterpret_cast<const char*>(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;
}
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 true;
}
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<char> 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