8000 Isolated Processes 10: Refactor ProcessReader by marti4d · Pull Request #198 · rust-minidump/minidump-writer · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions crates/linux/process-backend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,11 @@ pub mod regs;
/// This is the longest path length we guarantee we can handle, since we won't be able to allocate
/// in the fork of the crashed process. We can increase if necessary.
pub const MAX_PATH_LEN: usize = 256;

#[derive(Debug, serde::Deserialize, serde::Serialize)]
pub enum ProcessReaderKind {
Unspecified,
VirtualMem,
File,
Ptrace,
}
35 changes: 18 additions & 17 deletions crates/linux/process-backend/src/local/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::regs::*;
use crate::{ProcessReaderKind, regs::*};
use core::{
cell::RefCell,
ffi::{CStr, c_int, c_long, c_void},
Expand All @@ -22,18 +22,20 @@ type PtraceRequestType = core::ffi::c_int;
#[derive(Debug)]
pub struct Backend {
pid: pid_t,
process_reader: process_reader::ProcessReader,
syscall_invoker: RefCell<SyscallInvoker>,
}

impl Backend {
pub fn new(pid: libc::pid_t) -> Self {
Self {
pid,
process_reader: process_reader::ProcessReader::new(pid),
syscall_invoker: Default::default(),
}
}
pub fn process_reader(&self) -> ProcessReader {
ProcessReader(process_reader::ProcessReader::new(self.pid))
pub fn process_reader(&self) -> ProcessReader<'_> {
ProcessReader(&self.process_reader)
}
pub fn stop_process(&self) -> Result<(), Error> {
self.standard_syscall(|| unsafe { libc::kill(self.pid, libc::SIGSTOP) })
Expand Down Expand Up @@ -175,18 +177,17 @@ impl Backend {
.map_err(Error::PtracePeekUserFailed)
}

pub fn process_reader_for_virtual_mem(&self) -> ProcessReader {
ProcessReader(process_reader::ProcessReader::for_virtual_mem(self.pid))
}

pub fn process_reader_for_file(&self) -> Result<ProcessReader, Error> {
process_reader::ProcessReader::for_file(self.pid)
.map(ProcessReader)
.map_err(Error::ProcessReader)
}

pub fn process_reader_for_ptrace(&self) -> ProcessReader {
ProcessReader(process_reader::ProcessReader::for_ptrace(self.pid))
pub fn force_process_reader_kind(&mut self, kind: ProcessReaderKind) -> Result<(), Error> {
use ProcessReaderKind as K;
self.process_reader = match kind {
K::Unspecified => process_reader::ProcessReader::new(self.pid),
K::VirtualMem => process_reader::ProcessReader::for_virtual_mem(self.pid),
K::File => {
process_reader::ProcessReader::for_file(self.pid).map_err(Error::ProcessReader)?
}
K::Ptrace => process_reader::ProcessReader::for_ptrace(self.pid),
};
Ok(())
}

fn open_file(&self, path: &CStr) -> Result<OwnedFd, Error> {
Expand Down Expand Up @@ -392,9 +393,9 @@ impl Drop for DirReader {
}

#[derive(Debug)]
pub struct ProcessReader(process_reader::ProcessReader);
pub struct ProcessReader<'a>(&'a process_reader::ProcessReader);

impl ProcessReader {
impl<'a> ProcessReader<'a> {
pub fn read_at(&self, address: usize, buf: &mut [u8]) -> Result<usize, Error> {
self.0.read_at(address, buf).map_err(Error::ProcessReader)
}
Expand Down
30 changes: 23 additions & 7 deletions src/bin/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ mod linux {
super::*,
error_graph::ErrorList,
minidump_writer::{
LINUX_GATE_LIBRARY_NAME,
LINUX_GATE_LIBRARY_NAME, ProcessReaderKind,
minidump_writer::{MinidumpWriter, MinidumpWriterConfig},
},
std::ptr,
Expand Down Expand Up @@ -73,7 +73,7 @@ mod linux {
use minidump_writer::process_reader::ProcessReader;

let ppid = getppid();
let dumper = fail_on_soft_error!(
let mut dumper = fail_on_soft_error!(
soft_errors,
MinidumpWriterConfig::new(ppid, ppid).build_for_testing(&mut soft_errors)?
);
Expand All @@ -99,23 +99,39 @@ mod linux {

// virtual mem
{
validate(ProcessReader::for_virtual_mem(&dumper.process_inspector))
dumper
.process_inspector
.force_process_reader_kind(ProcessReaderKind::VirtualMem)
.unwrap();
validate(dumper.process_inspector.process_reader())
.map_err(|err| format!("failed to validate memory: {err}"))?;
}

// file
{
let reader = ProcessReader::for_file(&dumper.process_inspector)
.map_err(|err| format!("failed to open `/proc/{ppid}/mem`: {err}"))?;
validate(reader).map_err(|err| format!("failed to validate memory: {err}"))?;
dumper
.process_inspector
.force_process_reader_kind(ProcessReaderKind::File)
.unwrap();
validate(dumper.process_inspector.process_reader())
.map_err(|err| format!("failed to validate memory: {err}"))?;
}

// ptrace
{
validate(ProcessReader::for_ptrace(&dumper.process_inspector))
dumper
.process_inspector
.force_process_reader_kind(ProcessReaderKind::Ptrace)
.unwrap();
validate(dumper.process_inspector.process_reader())
.map_err(|err| format!("failed to validate memory: {err}"))?;
}

dumper
.process_inspector
.force_process_reader_kind(ProcessReaderKind::Unspecified)
.unwrap();

let stack_res = MinidumpWriter::copy_from_process(
&dumper.process_inspector,
stack_var,
Expand Down
2 changes: 1 addition & 1 deletion src/linux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

pub use {
maps_reader::LINUX_GATE_LIBRARY_NAME,
process_inspection::{Error as BackendError, process_reader},
process_inspection::{Error as BackendError, ProcessReaderKind, process_reader},
};

pub mod app_memory;
Expand Down
23 changes: 13 additions & 10 deletions src/linux/process_inspection/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use self::process_reader::ProcessReader;
use super::maps_reader;
use crate::module_reader::{ModuleMemoryReadError, ReadError, ReadModuleMemory};
use core::ffi::c_int;
use failspot::failspot;
use process_backend::{MAX_PATH_LEN, local, regs::*};
use process_reader::ProcessReader;
use std::{
borrow::Cow,
ffi::{CString, OsString},
Expand All @@ -14,6 +14,8 @@ use std::{

pub use process_backend::regs;

pub use process_backend::ProcessReaderKind;

pub mod process_reader;

#[derive(Debug)]
Expand All @@ -24,23 +26,16 @@ pub struct ProcessInspector {

#[derive(Debug)]
pub enum Backend {
Local {
backend: local::Backend,
process_reader_backend: local::ProcessReader,
},
Local { backend: local::Backend },
}

impl ProcessInspector {
pub fn local(pid: libc::pid_t) -> Self {
let backend = local::Backend::new(pid);
let process_reader_backend = backend.process_reader();

ProcessInspector {
pid,
backend: Backend::Local {
backend,
process_reader_backend,
},
backend: Backend::Local { backend },
}
}
pub fn process_reader(&self) -> ProcessReader<'_> {
Expand Down Expand Up @@ -161,6 +156,14 @@ impl ProcessInspector {
}
}
}

pub fn force_process_reader_kind(&mut self, kind: ProcessReaderKind) -> Result<(), Error> {
match &mut self.backend {
Backend::Local { backend, .. } => backend
.force_process_reader_kind(kind)
.map_err(Error::Local),
}
}
}

#[derive(Debug)]
Expand Down
66 changes: 6 additions & 60 deletions src/linux/process_inspection/process_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,81 +4,27 @@ use super::{
};
use crate::module_reader::ProcessModuleMemoryReader;

use process_backend::local;

pub type ProcessHandle = libc::pid_t;

#[derive(Debug)]
pub struct ProcessReader<'a> {
process_inspector: &'a ProcessInspector,
forced_backend: Option<ForcedBackend>,
}

#[derive(Debug)]
enum ForcedBackend {
Local(local::ProcessReader),
}

impl<'a> ProcessReader<'a> {
pub fn new(process_inspector: &'a ProcessInspector) -> Self {
Self {
process_inspector,
forced_backend: None,
}
}
pub fn for_virtual_mem(process_inspector: &'a ProcessInspector) -> Self {
let forced_backend = match &process_inspector.backend {
Backend::Local { backend, .. } => {
ForcedBackend::Local(backend.process_reader_for_virtual_mem())
}
};
Self {
process_inspector,
forced_backend: Some(forced_backend),
}
}
pub fn for_file(process_inspector: &'a ProcessInspector) -> Result<Self, Error> {
let forced_backend = match &process_inspector.backend {
Backend::Local { backend, .. } => {
ForcedBackend::Local(backend.process_reader_for_file().map_err(Error::Local)?)
}
};
Ok(Self {
process_inspector,
forced_backend: Some(forced_backend),
})
}
pub fn for_ptrace(process_inspector: &'a ProcessInspector) -> Self {
let forced_backend = match &process_inspector.backend {
Backend::Local { backend, .. } => {
ForcedBackend::Local(backend.process_reader_for_ptrace())
}
};
Self {
process_inspector,
forced_backend: Some(forced_backend),
}
Self { process_inspector }
}

/// Read memory from the process into the given buffer.
///
/// Returns the number of bytes read.
pub fn read(&self, src: usize, dst: &mut [u8]) -> Result<usize, CopyFromProcessError> {
if let Some(forced_backend) = &self.forced_backend {
match forced_backend {
ForcedBackend::Local(process_reader_backend) => process_reader_backend
.read_at(src, dst)
.map_err(Error::Local),
}
} else {
match &self.process_inspector.backend {
Backend::Local {
process_reader_backend,
..
} => process_reader_backend
.read_at(src, dst)
.map_err(Error::Local),
}
match &self.process_inspector.backend {
Backend::Local { backend } => backend
.process_reader()
.read_at(src, dst)
.map_err(Error::Local),
}
.map_err(CopyFromProcessError::Backend)
}
Expand Down
Loading
0