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
13 changes: 0 additions & 13 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 0 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,6 @@ memmap2 = "0.9"
byteorder = "1.4"
error-graph = { version = "0.1.1", features = ["serde"] }
failspot = "0.2.0"
nix = { version = "0.30", default-features = false, features = [
"mman",
"process",
"ptrace",
"signal",
"uio",
"user",
] }
process-backend = { path = "crates/linux/process-backend", features = ["testing"] }
# Used for parsing procfs info.
# default-features is disabled since it pulls in chrono
Expand Down
67 changes: 32 additions & 35 deletions src/bin/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@ mod linux {
LINUX_GATE_LIBRARY_NAME,
minidump_writer::{MinidumpWriter, MinidumpWriterConfig},
},
nix::{
sys::mman::{MapFlags, ProtFlags, mmap_anonymous},
unistd::getppid,
},
std::ptr,
};

macro_rules! test {
Expand All @@ -36,12 +33,15 @@ mod linux {
__result
}});

fn getppid() -> libc::pid_t {
unsafe { libc::getppid() }
}

fn test_setup() -> Result<()> {
let ppid = getppid();
fail_on_soft_error!(
soft_errors,
MinidumpWriterConfig::new(ppid.as_raw(), ppid.as_raw())
.build_for_testing(&mut soft_errors)?
MinidumpWriterConfig::new(ppid, ppid).build_for_testing(&mut soft_errors)?
);
Ok(())
}
Expand All @@ -50,17 +50,11 @@ mod linux {
let ppid = getppid();
let dumper = fail_on_soft_error!(
soft_errors,
MinidumpWriterConfig::new(ppid.as_raw(), ppid.as_raw())
.build_for_testing(&mut soft_errors)?
MinidumpWriterConfig::new(ppid, ppid).build_for_testing(&mut soft_errors)?
);
test!(!dumper.threads.is_empty(), "No threads");
test!(
dumper
.threads
.iter()
.filter(|x| x.tid == ppid.as_raw())
.count()
== 1,
dumper.threads.iter().filter(|x| x.tid == ppid).count() == 1,
"Thread found multiple times"
);

Expand All @@ -78,7 +72,7 @@ mod linux {
fn test_copy_from_process(stack_var: usize, heap_var: usize) -> Result<()> {
use minidump_writer::process_reader::ProcessReader;

let ppid = getppid().as_raw();
let ppid = getppid();
let mut dumper = fail_on_soft_error!(
soft_errors,
MinidumpWriterConfig::new(ppid, ppid).build_for_testing(&mut soft_errors)?
Expand Down Expand Up @@ -155,8 +149,7 @@ mod linux {

let dumper = fail_on_soft_error!(
soft_errors,
MinidumpWriterConfig::new(ppid.as_raw(), ppid.as_raw())
.build_for_testing(&mut soft_errors)?
MinidumpWriterConfig::new(ppid, ppid).build_for_testing(&mut soft_errors)?
);
dumper
.find_mapping(addr1)
Expand All @@ -171,7 +164,7 @@ mod linux {
}

fn test_file_id() -> Result<()> {
let ppid = getppid().as_raw();
let ppid = getppid();
let exe_link = format!("/proc/{ppid}/exe");
let exe_name = std::fs::read_link(exe_link)?.into_os_string();

Expand Down Expand Up @@ -201,8 +194,7 @@ mod linux {
// Now check that PtraceDumper interpreted the mappings properly.
let dumper = fail_on_soft_error!(
soft_errors,
MinidumpWriterConfig::new(getppid().as_raw(), getppid().as_raw())
.build_for_testing(&mut soft_errors)?
MinidumpWriterConfig::new(getppid(), getppid()).build_for_testing(&mut soft_errors)?
);
let mut mapping_count = 0;
for map in &dumper.mappings {
Expand All @@ -224,7 +216,7 @@ mod linux {
}

fn test_linux_gate_mapping_id() -> Result<()> {
let ppid = getppid().as_raw();
let ppid = getppid();
let mut dumper = fail_on_soft_error!(
soft_errors,
MinidumpWriterConfig::new(ppid, ppid).build_for_testing(&mut soft_errors)?
Expand All @@ -247,7 +239,7 @@ mod linux {
}

fn test_mappings_include_linux_gate() -> Result<()> {
let ppid = getppid().as_raw();
let ppid = getppid();
let dumper = fail_on_soft_error!(
soft_errors,
MinidumpWriterConfig::new(ppid, ppid).build_for_testing(&mut soft_errors)?
Expand Down Expand Up @@ -314,28 +306,33 @@ mod linux {
}

fn spawn_mmap_wait() -> Result<()> {
let page_size = nix::unistd::sysconf(nix::unistd::SysconfVar::PAGE_SIZE).unwrap();
let memory_size = std::num::NonZeroUsize::new(page_size.unwrap() as usize).unwrap();
let page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) };
assert!(page_size > 0);
let memory_size = std::num::NonZeroUsize::new(page_size as usize).unwrap();
// Get some memory to be mapped by the child-process
let mapped_mem = unsafe {
mmap_anonymous(
None,
memory_size,
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
MapFlags::MAP_PRIVATE | MapFlags::MAP_ANON,
)
.unwrap()
let ptr = libc::mmap(
ptr::null_mut(),
memory_size.into(),
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
-1,
0,
);
assert!(ptr != libc::MAP_FAILED);
ptr
};

println!("{} {}", mapped_mem.as_ptr() as usize, memory_size);
println!("{} {}", mapped_mem as usize, memory_size);
loop {
std::thread::park();
}
}

fn spawn_alloc_wait() -> Result<()> {
let page_size = nix::unistd::sysconf(nix::unistd::SysconfVar::PAGE_SIZE).unwrap();
let memory_size = page_size.unwrap() as usize;
let page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) };
assert!(page_size > 0);

let memory_size = page_size as usize;

let mut values = Vec::<u8>::with_capacity(memory_size);
for idx in 0..memory_size {
Expand Down
75 changes: 43 additions & 32 deletions src/linux/dumper_cpu_info/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use {
super::process_inspection::{self, ProcessInspector},
crate::{minidump_format::PlatformId, serializers::*},
nix::sys::utsname::uname,
std::{
ffi::{CStr, c_char},
mem,
},
};

cfg_if::cfg_if! {
Expand Down Expand Up @@ -57,39 +60,47 @@ pub fn os_information() -> (PlatformId, String) {
// This is quite unfortunate, but the primary reason that uname could fail
// would be if it failed to fill out the nodename (hostname) field, even
// though we don't care about that particular field at all
let info = uname().map_or_else(
|_e| {
let os = if platform_id == PlatformId::Linux {
"Linux"
} else {
"Android"
};
let info = (|| unsafe {
let mut uts_name = mem::zeroed();
if libc::uname(&mut uts_name) == -1 {
return None;
}

let machine = if cfg!(target_arch = "x86_64") {
"x86_64"
} else if cfg!(target_arch = "x86") {
"x86"
} else if cfg!(target_arch = "aarch64") {
"aarch64"
} else if cfg!(target_arch = "arm") {
"arm"
} else {
"<unknown>"
};
fn to_str(b: &[c_char]) -> &str {
let cstr = unsafe { CStr::from_ptr(b.as_ptr().cast()) };
cstr.to_str().unwrap_or("<unknown>")
}

// TODO: Fallback to other sources of information, eg /etc/os-release
format!("{os} <unknown> <unknown> {machine}")
},
|info| {
format!(
"{} {} {} {}",
info.sysname().to_str().unwrap_or("<unknown>"),
info.release().to_str().unwrap_or("<unknown>"),
info.version().to_str().unwrap_or("<unknown>"),
info.machine().to_str().unwrap_or("<unknown>"),
)
},
);
Some(format!(
"{} {} {} {}",
to_str(&uts_name.sysname),
to_str(&uts_name.release),
to_str(&uts_name.version),
to_str(&uts_name.machine),
))
})()
.unwrap_or_else(|| {
let os = if platform_id == PlatformId::Linux {
"Linux"
} else {
"Android"
};

let machine = if cfg!(target_arch = "x86_64") {
"x86_64"
} else if cfg!(target_arch = "x86") {
"x86"
} else if cfg!(target_arch = "aarch64") {
"aarch64"
} else if cfg!(target_arch = "arm") {
"arm"
} else {
"<unknown>"
};

// TODO: Fallback to other sources of information, eg /etc/os-release
format!("{os} <unknown> <unknown> {machine}")
});

(platform_id, info)
}
38 changes: 3 additions & 35 deletions src/linux/minidump_writer/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use {
},
error_graph::ErrorList,
procfs_core::ProcError,
std::ffi::OsString,
std::ffi::{OsString, c_int},
thiserror::Error,
};

Expand Down Expand Up @@ -97,38 +97,12 @@ pub enum WriterError {
#[serde(skip)]
serde_json::Error,
),
#[error("nix::ptrace::attach(Pid={0}) failed")]
PtraceAttachError(
Pid,
#[source]
#[serde(serialize_with = "serialize_nix_error")]
nix::Error,
),
#[error("nix::ptrace::detach(Pid={0}) failed")]
PtraceDetachError(
Pid,
#[source]
#[serde(serialize_with = "serialize_nix_error")]
nix::Error,
),
#[error("wait::waitpid(Pid={0}) failed")]
WaitPidError(
Pid,
#[source]
#[serde(serialize_with = "serialize_nix_error")]
nix::Error,
),
#[error("nix::ptrace::attach(Pid={0}) failed: {1}")]
PtraceAttachError(Pid, c_int),
#[error("Skipped thread {0} due to it being part of the seccomp sandbox's trusted code")]
DetachSkippedThread(Pid),
#[error("Maps reader error")]
MapsReaderError(#[from] MapsReaderError),
#[error("Failed to get PAGE_SIZE from system")]
SysConfError(
#[from]
#[serde(serialize_with = "serialize_nix_error")]
nix::Error,
),

#[error("No mapping for stack pointer found")]
NoStackPointerMapping,
#[error("Failed slice conversion")]
Expand Down Expand Up @@ -168,12 +142,6 @@ pub enum InitError {
#[cfg(target_os = "android")]
#[error("Failed Android specific late init")]
AndroidLateInitError(#[from] AndroidError),
#[error("Failed to read the page size")]
PageSizeError(
#[from]
#[serde(serialize_with = "serialize_nix_error")]
nix::Error,
),
#[error("Ptrace does not function within the same process")]
CannotPtraceSameProcess,
#[error("Failed to stop the target process")]
Expand Down
10 changes: 6 additions & 4 deletions src/linux/minidump_writer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,9 +279,11 @@ impl MinidumpWriter {
soft_errors.push(InitError::EnumerateMappingsFailed(Box::new(e)));
}

self.page_size = nix::unistd::sysconf(nix::unistd::SysconfVar::PAGE_SIZE)?
.expect("page size apparently unlimited: doesn't make sense.")
as usize;
self.page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE).try_into().unwrap() };
assert!(
self.page_size > 0,
"somehow we weren't able to get the page size - should never happen"
);

let threads_count = self.threads.len();

Expand Down Expand Up @@ -577,7 +579,7 @@ impl MinidumpWriter {

self.threads_suspended = true;

failspot::failspot!(<crate::FailSpotName>::SuspendThreads soft_errors.push(WriterError::PtraceAttachError(1234, nix::Error::EPERM)))
failspot::failspot!(<crate::FailSpotName>::SuspendThreads soft_errors.push(WriterError::PtraceAttachError(1234, libc::EPERM)))
}

fn resume_threads(&mut self, mut soft_errors: impl WriteErrorList<WriterError>) {
Expand Down
7 changes: 0 additions & 7 deletions src/linux/serializers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,6 @@ pub fn serialize_goblin_error<S: Serializer>(
) -> Result<S::Ok, S::Error> {
serialize_generic_error(error, serializer)
}
/// Serialize [nix::Error]
pub fn serialize_nix_error<S: Serializer>(
error: &nix::Error,
serializer: S,
) -> Result<S::Ok, S::Error> {
serialize_generic_error(error, serializer)
}
/// Serialize [procfs_core::ProcError]
pub fn serialize_proc_error<S: Serializer>(
error: &procfs_core::ProcError,
Expand Down
Loading
Loading