mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-09 22:16:13 +00:00
Construct ProcessMemoryLinux using PtraceConnection
Update ProcessMemoryLinux to be constructed from PtraceConnection instead of being Initialize()d with a pid_t. This allows consolidating PtraceClient's BrokeredMemory with ProcessMemoryLinux and providing the PtraceConnection as a alternative to the memory file (previously only done for brokered connections). Change-Id: I1363e208030eaf595fb8051e9a2c6b255c1f9886 Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/3072402 Reviewed-by: Mark Mentovai <mark@chromium.org> Commit-Queue: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
parent
d5d78c1469
commit
78bcb55e1c
@ -30,6 +30,10 @@
|
||||
#include "util/misc/from_pointer_cast.h"
|
||||
#include "util/process/process_memory_native.h"
|
||||
|
||||
#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS)
|
||||
#include "test/linux/fake_ptrace_connection.h"
|
||||
#endif
|
||||
|
||||
namespace crashpad {
|
||||
namespace test {
|
||||
namespace {
|
||||
@ -102,8 +106,14 @@ void ExpectCrashpadInfo(ProcessType process,
|
||||
VMAddress extra_memory_address,
|
||||
VMAddress simple_annotations_address,
|
||||
VMAddress annotations_list_address) {
|
||||
#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS)
|
||||
FakePtraceConnection connection;
|
||||
ASSERT_TRUE(connection.Initialize(process));
|
||||
ProcessMemoryLinux memory(&connection);
|
||||
#else
|
||||
ProcessMemoryNative memory;
|
||||
ASSERT_TRUE(memory.Initialize(process));
|
||||
#endif
|
||||
|
||||
ProcessMemoryRange range;
|
||||
ASSERT_TRUE(range.Initialize(&memory, is_64_bit));
|
||||
|
@ -32,6 +32,10 @@
|
||||
#include "util/misc/from_pointer_cast.h"
|
||||
#include "util/process/process_memory_native.h"
|
||||
|
||||
#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS)
|
||||
#include "test/linux/fake_ptrace_connection.h"
|
||||
#endif
|
||||
|
||||
namespace crashpad {
|
||||
namespace test {
|
||||
namespace {
|
||||
@ -90,8 +94,14 @@ void ExpectAnnotations(ProcessType process,
|
||||
bool is_64_bit,
|
||||
VMAddress simple_map_address,
|
||||
VMAddress annotation_list_address) {
|
||||
#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS)
|
||||
FakePtraceConnection connection;
|
||||
ASSERT_TRUE(connection.Initialize(process));
|
||||
ProcessMemoryLinux memory(&connection);
|
||||
#else
|
||||
ProcessMemoryNative memory;
|
||||
ASSERT_TRUE(memory.Initialize(process));
|
||||
#endif
|
||||
|
||||
ProcessMemoryRange range;
|
||||
ASSERT_TRUE(range.Initialize(&memory, is_64_bit));
|
||||
|
@ -127,21 +127,22 @@ void ReadThisExecutableInTarget(ProcessType process,
|
||||
constexpr bool am_64_bit = false;
|
||||
#endif // ARCH_CPU_64_BITS
|
||||
|
||||
ProcessMemoryNative memory;
|
||||
ASSERT_TRUE(memory.Initialize(process));
|
||||
ProcessMemoryRange range;
|
||||
ASSERT_TRUE(range.Initialize(&memory, am_64_bit));
|
||||
|
||||
VMAddress elf_address;
|
||||
#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
|
||||
FakePtraceConnection connection;
|
||||
ASSERT_TRUE(connection.Initialize(process));
|
||||
ProcessMemoryLinux memory(&connection);
|
||||
LocateExecutable(&connection, &memory, &elf_address);
|
||||
#elif defined(OS_FUCHSIA)
|
||||
ProcessMemoryFuchsia memory;
|
||||
ASSERT_TRUE(memory.Initialize(process));
|
||||
LocateExecutable(process, &memory, &elf_address);
|
||||
#endif
|
||||
ASSERT_NO_FATAL_FAILURE();
|
||||
|
||||
ProcessMemoryRange range;
|
||||
ASSERT_TRUE(range.Initialize(&memory, am_64_bit));
|
||||
|
||||
ElfImageReader reader;
|
||||
ASSERT_TRUE(reader.Initialize(range, elf_address));
|
||||
|
||||
@ -191,8 +192,15 @@ void ReadLibcInTarget(ProcessType process,
|
||||
constexpr bool am_64_bit = false;
|
||||
#endif // ARCH_CPU_64_BITS
|
||||
|
||||
#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS)
|
||||
FakePtraceConnection connection;
|
||||
ASSERT_TRUE(connection.Initialize(process));
|
||||
ProcessMemoryLinux memory(&connection);
|
||||
#else
|
||||
ProcessMemoryNative memory;
|
||||
ASSERT_TRUE(memory.Initialize(process));
|
||||
#endif
|
||||
|
||||
ProcessMemoryRange range;
|
||||
ASSERT_TRUE(range.Initialize(&memory, am_64_bit));
|
||||
|
||||
|
@ -83,8 +83,7 @@ void TestAgainstTarget(PtraceConnection* connection) {
|
||||
ASSERT_EQ(exe_mappings->Count(), 1u);
|
||||
LinuxVMAddress elf_address = exe_mappings->Next()->range.Base();
|
||||
|
||||
ProcessMemoryLinux memory;
|
||||
ASSERT_TRUE(memory.Initialize(connection->GetProcessID()));
|
||||
ProcessMemoryLinux memory(connection);
|
||||
ProcessMemoryRange range;
|
||||
ASSERT_TRUE(range.Initialize(&memory, connection->Is64Bit()));
|
||||
|
||||
|
@ -20,6 +20,10 @@
|
||||
#include "util/misc/from_pointer_cast.h"
|
||||
#include "util/process/process_memory_linux.h"
|
||||
|
||||
#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS)
|
||||
#include "test/linux/fake_ptrace_connection.h"
|
||||
#endif
|
||||
|
||||
namespace crashpad {
|
||||
namespace test {
|
||||
namespace {
|
||||
@ -27,11 +31,12 @@ namespace {
|
||||
class AllowedAnnotationsTest : public testing::Test {
|
||||
public:
|
||||
void SetUp() override {
|
||||
ASSERT_TRUE(memory_.Initialize(getpid()));
|
||||
ASSERT_TRUE(connection_.Initialize(getpid()));
|
||||
|
||||
#if defined(ARCH_CPU_64_BITS)
|
||||
ASSERT_TRUE(range_.Initialize(&memory_, true));
|
||||
ASSERT_TRUE(range_.Initialize(connection_.Memory(), true));
|
||||
#else
|
||||
ASSERT_TRUE(range_.Initialize(&memory_, false));
|
||||
ASSERT_TRUE(range_.Initialize(connection_.Memory(), false));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -41,7 +46,7 @@ class AllowedAnnotationsTest : public testing::Test {
|
||||
range_, FromPointerCast<VMAddress>(address), &allowed_annotations_);
|
||||
}
|
||||
|
||||
ProcessMemoryLinux memory_;
|
||||
FakePtraceConnection connection_;
|
||||
ProcessMemoryRange range_;
|
||||
std::vector<std::string> allowed_annotations_;
|
||||
};
|
||||
|
@ -83,12 +83,7 @@ bool FakePtraceConnection::ReadFileContents(const base::FilePath& path,
|
||||
ProcessMemory* FakePtraceConnection::Memory() {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
if (!memory_) {
|
||||
auto mem = std::make_unique<ProcessMemoryLinux>();
|
||||
if (mem->Initialize(pid_)) {
|
||||
memory_ = std::move(mem);
|
||||
} else {
|
||||
ADD_FAILURE();
|
||||
}
|
||||
memory_ = std::make_unique<ProcessMemoryLinux>(this);
|
||||
}
|
||||
return memory_.get();
|
||||
}
|
||||
@ -99,5 +94,12 @@ bool FakePtraceConnection::Threads(std::vector<pid_t>* threads) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ssize_t FakePtraceConnection::ReadUpTo(VMAddress address,
|
||||
size_t size,
|
||||
void* buffer) {
|
||||
NOTREACHED();
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace crashpad
|
||||
|
@ -65,6 +65,9 @@ class FakePtraceConnection : public PtraceConnection {
|
||||
//! \todo Not yet implemented.
|
||||
bool Threads(std::vector<pid_t>* threads) override;
|
||||
|
||||
//! \\todo Not yet implemented.
|
||||
ssize_t ReadUpTo(VMAddress address, size_t size, void* buffer) override;
|
||||
|
||||
private:
|
||||
std::set<pid_t> attachments_;
|
||||
std::unique_ptr<ProcessMemoryLinux> memory_;
|
||||
|
@ -95,8 +95,7 @@ void TestAgainstCloneOrSelf(pid_t pid) {
|
||||
ASSERT_TRUE(aux.GetValue(AT_EGID, &egid));
|
||||
EXPECT_EQ(egid, getegid());
|
||||
|
||||
ProcessMemoryLinux memory;
|
||||
ASSERT_TRUE(memory.Initialize(pid));
|
||||
ProcessMemoryLinux memory(&connection);
|
||||
|
||||
LinuxVMAddress platform_addr;
|
||||
ASSERT_TRUE(aux.GetValue(AT_PLATFORM, &platform_addr));
|
||||
|
@ -39,10 +39,6 @@ bool DirectPtraceConnection::Initialize(pid_t pid) {
|
||||
}
|
||||
pid_ = pid;
|
||||
|
||||
if (!memory_.Initialize(pid)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
INITIALIZATION_STATE_SET_VALID(initialized_);
|
||||
return true;
|
||||
}
|
||||
@ -79,7 +75,10 @@ bool DirectPtraceConnection::ReadFileContents(const base::FilePath& path,
|
||||
|
||||
ProcessMemory* DirectPtraceConnection::Memory() {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
return &memory_;
|
||||
if (!memory_) {
|
||||
memory_ = std::make_unique<ProcessMemoryLinux>(this);
|
||||
}
|
||||
return memory_.get();
|
||||
}
|
||||
|
||||
bool DirectPtraceConnection::Threads(std::vector<pid_t>* threads) {
|
||||
@ -87,4 +86,10 @@ bool DirectPtraceConnection::Threads(std::vector<pid_t>* threads) {
|
||||
return ReadThreadIDs(pid_, threads);
|
||||
}
|
||||
|
||||
ssize_t DirectPtraceConnection::ReadUpTo(VMAddress address,
|
||||
size_t size,
|
||||
void* buffer) {
|
||||
return ptracer_.ReadUpTo(pid_, address, size, static_cast<char*>(buffer));
|
||||
}
|
||||
|
||||
} // namespace crashpad
|
||||
|
@ -57,10 +57,11 @@ class DirectPtraceConnection : public PtraceConnection {
|
||||
std::string* contents) override;
|
||||
ProcessMemory* Memory() override;
|
||||
bool Threads(std::vector<pid_t>* threads) override;
|
||||
ssize_t ReadUpTo(VMAddress, size_t size, void* buffer) override;
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<ScopedPtraceAttach>> attachments_;
|
||||
ProcessMemoryLinux memory_;
|
||||
std::unique_ptr<ProcessMemory> memory_;
|
||||
pid_t pid_;
|
||||
Ptracer ptracer_;
|
||||
InitializationStateDcheck initialized_;
|
||||
|
@ -151,8 +151,7 @@ class SameBitnessTest : public Multiprocess {
|
||||
broker_thread.Start();
|
||||
|
||||
PtraceClient client;
|
||||
ASSERT_TRUE(client.Initialize(
|
||||
client_sock.get(), ChildPID(), /* try_direct_memory= */ false));
|
||||
ASSERT_TRUE(client.Initialize(client_sock.get(), ChildPID()));
|
||||
|
||||
EXPECT_EQ(client.GetProcessID(), ChildPID());
|
||||
|
||||
@ -177,32 +176,26 @@ class SameBitnessTest : public Multiprocess {
|
||||
ASSERT_TRUE(client.GetThreadInfo(child2_tid, &info2));
|
||||
EXPECT_EQ(info2.thread_specific_data_address, child2_tls);
|
||||
|
||||
ProcessMemory* memory = client.Memory();
|
||||
ASSERT_TRUE(memory);
|
||||
|
||||
auto buffer = std::make_unique<char[]>(mapping_.len());
|
||||
ASSERT_TRUE(memory->Read(
|
||||
mapping_.addr_as<VMAddress>(), mapping_.len(), buffer.get()));
|
||||
auto expected_buffer = mapping_.addr_as<char*>();
|
||||
for (size_t index = 0; index < mapping_.len(); ++index) {
|
||||
EXPECT_EQ(buffer[index], expected_buffer[index]);
|
||||
}
|
||||
|
||||
char first;
|
||||
ASSERT_TRUE(
|
||||
memory->Read(mapping_.addr_as<VMAddress>(), sizeof(first), &first));
|
||||
ASSERT_EQ(
|
||||
client.ReadUpTo(mapping_.addr_as<VMAddress>(), sizeof(first), &first),
|
||||
1);
|
||||
EXPECT_EQ(first, expected_buffer[0]);
|
||||
|
||||
char last;
|
||||
ASSERT_TRUE(memory->Read(mapping_.addr_as<VMAddress>() + mapping_.len() - 1,
|
||||
sizeof(last),
|
||||
&last));
|
||||
ASSERT_EQ(
|
||||
client.ReadUpTo(mapping_.addr_as<VMAddress>() + mapping_.len() - 1,
|
||||
sizeof(last),
|
||||
&last),
|
||||
1);
|
||||
EXPECT_EQ(last, expected_buffer[mapping_.len() - 1]);
|
||||
|
||||
char unmapped;
|
||||
EXPECT_FALSE(memory->Read(mapping_.addr_as<VMAddress>() + mapping_.len(),
|
||||
EXPECT_EQ(client.ReadUpTo(mapping_.addr_as<VMAddress>() + mapping_.len(),
|
||||
sizeof(unmapped),
|
||||
&unmapped));
|
||||
&unmapped),
|
||||
-1);
|
||||
|
||||
std::string file_root = file_dir.value() + '/';
|
||||
broker.SetFileRoot(file_root.c_str());
|
||||
|
@ -143,7 +143,7 @@ PtraceClient::~PtraceClient() {
|
||||
}
|
||||
}
|
||||
|
||||
bool PtraceClient::Initialize(int sock, pid_t pid, bool try_direct_memory) {
|
||||
bool PtraceClient::Initialize(int sock, pid_t pid) {
|
||||
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
|
||||
sock_ = sock;
|
||||
pid_ = pid;
|
||||
@ -166,16 +166,6 @@ bool PtraceClient::Initialize(int sock, pid_t pid, bool try_direct_memory) {
|
||||
}
|
||||
is_64_bit_ = is_64_bit == ExceptionHandlerProtocol::kBoolTrue;
|
||||
|
||||
if (try_direct_memory) {
|
||||
auto direct_mem = std::make_unique<ProcessMemoryLinux>();
|
||||
if (direct_mem->Initialize(pid)) {
|
||||
memory_.reset(direct_mem.release());
|
||||
}
|
||||
}
|
||||
if (!memory_) {
|
||||
memory_ = std::make_unique<BrokeredMemory>(this);
|
||||
}
|
||||
|
||||
INITIALIZATION_STATE_SET_VALID(initialized_);
|
||||
return true;
|
||||
}
|
||||
@ -260,6 +250,9 @@ bool PtraceClient::ReadFileContents(const base::FilePath& path,
|
||||
|
||||
ProcessMemory* PtraceClient::Memory() {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
if (!memory_) {
|
||||
memory_ = std::make_unique<ProcessMemoryLinux>(this);
|
||||
}
|
||||
return memory_.get();
|
||||
}
|
||||
|
||||
@ -308,20 +301,7 @@ bool PtraceClient::Threads(std::vector<pid_t>* threads) {
|
||||
return true;
|
||||
}
|
||||
|
||||
PtraceClient::BrokeredMemory::BrokeredMemory(PtraceClient* client)
|
||||
: ProcessMemory(), client_(client) {}
|
||||
|
||||
PtraceClient::BrokeredMemory::~BrokeredMemory() = default;
|
||||
|
||||
ssize_t PtraceClient::BrokeredMemory::ReadUpTo(VMAddress address,
|
||||
size_t size,
|
||||
void* buffer) const {
|
||||
return client_->ReadUpTo(address, size, buffer);
|
||||
}
|
||||
|
||||
ssize_t PtraceClient::ReadUpTo(VMAddress address,
|
||||
size_t size,
|
||||
void* buffer) const {
|
||||
ssize_t PtraceClient::ReadUpTo(VMAddress address, size_t size, void* buffer) {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
char* buffer_c = reinterpret_cast<char*>(buffer);
|
||||
|
||||
|
@ -46,11 +46,8 @@ class PtraceClient : public PtraceConnection {
|
||||
//! ownership of the socket.
|
||||
//! \param[in] pid The process ID of the process to form a PtraceConnection
|
||||
//! with.
|
||||
//! \param[in] try_direct_memory If `true` the client will attempt to support
|
||||
//! memory reading operations by directly acessing the target process'
|
||||
//! /proc/[pid]/mem file.
|
||||
//! \return `true` on success. `false` on failure with a message logged.
|
||||
bool Initialize(int sock, pid_t pid, bool try_direct_memory = true);
|
||||
bool Initialize(int sock, pid_t pid);
|
||||
|
||||
// PtraceConnection:
|
||||
|
||||
@ -62,24 +59,9 @@ class PtraceClient : public PtraceConnection {
|
||||
std::string* contents) override;
|
||||
ProcessMemory* Memory() override;
|
||||
bool Threads(std::vector<pid_t>* threads) override;
|
||||
ssize_t ReadUpTo(VMAddress address, size_t size, void* buffer) override;
|
||||
|
||||
private:
|
||||
class BrokeredMemory : public ProcessMemory {
|
||||
public:
|
||||
explicit BrokeredMemory(PtraceClient* client);
|
||||
~BrokeredMemory();
|
||||
|
||||
ssize_t ReadUpTo(VMAddress address,
|
||||
size_t size,
|
||||
void* buffer) const override;
|
||||
|
||||
private:
|
||||
PtraceClient* client_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BrokeredMemory);
|
||||
};
|
||||
|
||||
ssize_t ReadUpTo(VMAddress address, size_t size, void* buffer) const;
|
||||
bool SendFilePath(const char* path, size_t length);
|
||||
|
||||
std::unique_ptr<ProcessMemory> memory_;
|
||||
|
@ -73,6 +73,20 @@ class PtraceConnection {
|
||||
//! this method returns `false`, \a threads may contain a partial list of
|
||||
//! thread IDs.
|
||||
virtual bool Threads(std::vector<pid_t>* threads) = 0;
|
||||
|
||||
//! \brief Copies memory from the connected process into a caller-provided
|
||||
//! buffer in the current process, up to a maximum number of bytes.
|
||||
//!
|
||||
//! \param[in] address The address, in the connected process' address space,
|
||||
//! of the memory region to copy.
|
||||
//! \param[in] size The maximum size, in bytes, of the memory region to copy.
|
||||
//! \a buffer must be at least this size.
|
||||
//! \param[out] buffer The buffer into which the contents of the other
|
||||
//! process' memory will be copied.
|
||||
//!
|
||||
//! \return the number of bytes copied, 0 if there is no more data to read, or
|
||||
//! -1 on failure with a message logged.
|
||||
virtual ssize_t ReadUpTo(VMAddress address, size_t size, void* buffer) = 0;
|
||||
};
|
||||
|
||||
} // namespace crashpad
|
||||
|
@ -27,38 +27,37 @@
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
ProcessMemoryLinux::ProcessMemoryLinux()
|
||||
: ProcessMemory(), mem_fd_(), pid_(-1), initialized_() {}
|
||||
ProcessMemoryLinux::ProcessMemoryLinux(PtraceConnection* connection)
|
||||
: ProcessMemory(), mem_fd_() {
|
||||
char path[32];
|
||||
snprintf(path, sizeof(path), "/proc/%d/mem", connection->GetProcessID());
|
||||
mem_fd_.reset(HANDLE_EINTR(open(path, O_RDONLY | O_NOCTTY | O_CLOEXEC)));
|
||||
if (mem_fd_.is_valid()) {
|
||||
read_up_to_ = [this](VMAddress address, size_t size, void* buffer) {
|
||||
ssize_t bytes_read =
|
||||
HANDLE_EINTR(pread64(mem_fd_.get(), buffer, size, address));
|
||||
if (bytes_read < 0) {
|
||||
PLOG(ERROR) << "pread64";
|
||||
}
|
||||
return bytes_read;
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
read_up_to_ = std::bind(&PtraceConnection::ReadUpTo,
|
||||
connection,
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
std::placeholders::_3);
|
||||
}
|
||||
|
||||
ProcessMemoryLinux::~ProcessMemoryLinux() {}
|
||||
|
||||
bool ProcessMemoryLinux::Initialize(pid_t pid) {
|
||||
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
|
||||
pid_ = pid;
|
||||
char path[32];
|
||||
snprintf(path, sizeof(path), "/proc/%d/mem", pid_);
|
||||
mem_fd_.reset(HANDLE_EINTR(open(path, O_RDONLY | O_NOCTTY | O_CLOEXEC)));
|
||||
if (!mem_fd_.is_valid()) {
|
||||
PLOG(ERROR) << "open";
|
||||
return false;
|
||||
}
|
||||
INITIALIZATION_STATE_SET_VALID(initialized_);
|
||||
return true;
|
||||
}
|
||||
|
||||
ssize_t ProcessMemoryLinux::ReadUpTo(VMAddress address,
|
||||
size_t size,
|
||||
void* buffer) const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
DCHECK(mem_fd_.is_valid());
|
||||
DCHECK_LE(size, size_t{std::numeric_limits<ssize_t>::max()});
|
||||
|
||||
ssize_t bytes_read =
|
||||
HANDLE_EINTR(pread64(mem_fd_.get(), buffer, size, address));
|
||||
if (bytes_read < 0) {
|
||||
PLOG(ERROR) << "pread64";
|
||||
}
|
||||
return bytes_read;
|
||||
return read_up_to_(address, size, buffer);
|
||||
}
|
||||
|
||||
} // namespace crashpad
|
||||
|
@ -17,12 +17,13 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "base/files/scoped_file.h"
|
||||
#include "base/macros.h"
|
||||
#include "util/linux/ptrace_connection.h"
|
||||
#include "util/misc/address_types.h"
|
||||
#include "util/misc/initialization_state_dcheck.h"
|
||||
#include "util/process/process_memory.h"
|
||||
|
||||
namespace crashpad {
|
||||
@ -30,26 +31,14 @@ namespace crashpad {
|
||||
//! \brief Accesses the memory of another Linux process.
|
||||
class ProcessMemoryLinux final : public ProcessMemory {
|
||||
public:
|
||||
ProcessMemoryLinux();
|
||||
explicit ProcessMemoryLinux(PtraceConnection* connection);
|
||||
~ProcessMemoryLinux();
|
||||
|
||||
//! \brief Initializes this object to read the memory of a process whose ID
|
||||
//! is \a pid.
|
||||
//!
|
||||
//! This method must be called successfully prior to calling any other method
|
||||
//! in this class.
|
||||
//!
|
||||
//! \param[in] pid The process ID of a target process.
|
||||
//!
|
||||
//! \return `true` on success, `false` on failure with a message logged.
|
||||
bool Initialize(pid_t pid);
|
||||
|
||||
private:
|
||||
ssize_t ReadUpTo(VMAddress address, size_t size, void* buffer) const override;
|
||||
|
||||
std::function<ssize_t(VMAddress, size_t, void*)> read_up_to_;
|
||||
base::ScopedFD mem_fd_;
|
||||
pid_t pid_;
|
||||
InitializationStateDcheck initialized_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ProcessMemoryLinux);
|
||||
};
|
||||
|
@ -23,6 +23,10 @@
|
||||
#include "util/misc/from_pointer_cast.h"
|
||||
#include "util/process/process_memory_native.h"
|
||||
|
||||
#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS)
|
||||
#include "test/linux/fake_ptrace_connection.h"
|
||||
#endif
|
||||
|
||||
namespace crashpad {
|
||||
namespace test {
|
||||
namespace {
|
||||
@ -39,8 +43,14 @@ TEST(ProcessMemoryRange, Basic) {
|
||||
constexpr bool is_64_bit = false;
|
||||
#endif // ARCH_CPU_64_BITS
|
||||
|
||||
#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS)
|
||||
FakePtraceConnection connection;
|
||||
ASSERT_TRUE(connection.Initialize(GetSelfProcess()));
|
||||
ProcessMemoryLinux memory(&connection);
|
||||
#else
|
||||
ProcessMemoryNative memory;
|
||||
ASSERT_TRUE(memory.Initialize(GetSelfProcess()));
|
||||
#endif // OS_ANDROID || OS_LINUX || OS_CHROMEOS
|
||||
|
||||
ProcessMemoryRange range;
|
||||
ASSERT_TRUE(range.Initialize(&memory, is_64_bit));
|
||||
|
@ -19,13 +19,23 @@
|
||||
#include "util/misc/from_pointer_cast.h"
|
||||
#include "util/process/process_memory_native.h"
|
||||
|
||||
#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS)
|
||||
#include "test/linux/fake_ptrace_connection.h"
|
||||
#endif
|
||||
|
||||
namespace crashpad {
|
||||
namespace test {
|
||||
namespace {
|
||||
|
||||
TEST(ProcessMemorySanitized, DenyDisallowedMemory) {
|
||||
#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS)
|
||||
FakePtraceConnection connection;
|
||||
ASSERT_TRUE(connection.Initialize(GetSelfProcess()));
|
||||
ProcessMemoryLinux memory(&connection);
|
||||
#else
|
||||
ProcessMemoryNative memory;
|
||||
ASSERT_TRUE(memory.Initialize(GetSelfProcess()));
|
||||
#endif // OS_ANDROID || OS_LINUX || OS_CHROMEOS
|
||||
|
||||
char c = 42;
|
||||
char out;
|
||||
@ -41,8 +51,14 @@ TEST(ProcessMemorySanitized, DenyDisallowedMemory) {
|
||||
}
|
||||
|
||||
TEST(ProcessMemorySanitized, AllowedMemory) {
|
||||
#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS)
|
||||
FakePtraceConnection connection;
|
||||
ASSERT_TRUE(connection.Initialize(GetSelfProcess()));
|
||||
ProcessMemoryLinux memory(&connection);
|
||||
#else
|
||||
ProcessMemoryNative memory;
|
||||
ASSERT_TRUE(memory.Initialize(GetSelfProcess()));
|
||||
#endif // OS_ANDROID || OS_LINUX || OS_CHROMEOS
|
||||
|
||||
char str[4] = "ABC";
|
||||
char out[4];
|
||||
|
@ -34,6 +34,11 @@
|
||||
#include "test/mac/mach_multiprocess.h"
|
||||
#endif // defined(OS_APPLE)
|
||||
|
||||
#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS)
|
||||
#include "test/linux/fake_ptrace_connection.h"
|
||||
#include "util/linux/direct_ptrace_connection.h"
|
||||
#endif // OS_ANDROID || OS_LINUX || OS_CHROMEOS
|
||||
|
||||
namespace crashpad {
|
||||
namespace test {
|
||||
namespace {
|
||||
@ -148,8 +153,14 @@ class ReadTest : public MultiprocessAdaptor {
|
||||
}
|
||||
|
||||
void DoTest(ProcessType process, size_t region_size, VMAddress address) {
|
||||
#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS)
|
||||
FakePtraceConnection connection;
|
||||
ASSERT_TRUE(connection.Initialize(process));
|
||||
ProcessMemoryLinux memory(&connection);
|
||||
#else
|
||||
ProcessMemoryNative memory;
|
||||
ASSERT_TRUE(memory.Initialize(process));
|
||||
#endif // OS_ANDROID || OS_LINUX || OS_CHROMEOS
|
||||
|
||||
std::unique_ptr<char[]> result(new char[region_size]);
|
||||
|
||||
@ -328,8 +339,14 @@ class ReadCStringTest : public MultiprocessAdaptor {
|
||||
VMAddress local_empty_address,
|
||||
VMAddress local_short_address,
|
||||
VMAddress long_string_address) {
|
||||
#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS)
|
||||
FakePtraceConnection connection;
|
||||
ASSERT_TRUE(connection.Initialize(process));
|
||||
ProcessMemoryLinux memory(&connection);
|
||||
#else
|
||||
ProcessMemoryNative memory;
|
||||
ASSERT_TRUE(memory.Initialize(process));
|
||||
#endif // OS_ANDROID || OS_LINUX || OS_CHROMEOS
|
||||
|
||||
Compare(memory, const_empty_address, kConstCharEmpty);
|
||||
Compare(memory, const_short_address, kConstCharShort);
|
||||
@ -399,8 +416,14 @@ class ReadUnmappedTest : public MultiprocessAdaptor {
|
||||
}
|
||||
|
||||
void DoTest(ProcessType process, VMAddress address) {
|
||||
#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS)
|
||||
DirectPtraceConnection connection;
|
||||
ASSERT_TRUE(connection.Initialize(process));
|
||||
ProcessMemoryLinux memory(&connection);
|
||||
#else
|
||||
ProcessMemoryNative memory;
|
||||
ASSERT_TRUE(memory.Initialize(process));
|
||||
#endif // OS_ANDROID || OS_LINUX || OS_CHROMEOS
|
||||
|
||||
VMAddress page_addr1 = address;
|
||||
VMAddress page_addr2 = page_addr1 + base::GetPageSize();
|
||||
@ -525,8 +548,14 @@ class ReadCStringUnmappedTest : public MultiprocessAdaptor {
|
||||
|
||||
void DoTest(ProcessType process,
|
||||
const std::vector<StringDataInChildProcess>& strings) {
|
||||
#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS)
|
||||
DirectPtraceConnection connection;
|
||||
ASSERT_TRUE(connection.Initialize(process));
|
||||
ProcessMemoryLinux memory(&connection);
|
||||
#else
|
||||
ProcessMemoryNative memory;
|
||||
ASSERT_TRUE(memory.Initialize(process));
|
||||
#endif // OS_ANDROID || OS_LINUX || OS_CHROMEOS
|
||||
|
||||
std::string result;
|
||||
result.reserve(kChildProcessStringLength + 1);
|
||||
|
Loading…
x
Reference in New Issue
Block a user