Skip to content
Open
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
29 changes: 21 additions & 8 deletions crates/tracexec-backend-ptrace/src/ptrace/tracer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ use std::{
time::Duration,
};

use color_eyre::eyre::{
bail,
eyre,
};
use enumflags2::BitFlags;
use nix::{
errno::Errno,
Expand Down Expand Up @@ -118,6 +122,14 @@ pub trait BuildPtraceTracer: Sealed {

impl BuildPtraceTracer for TracerBuilder {
fn build_ptrace(self) -> color_eyre::Result<(Tracer, SpawnToken)> {
let mode = self.mode.ok_or_else(|| eyre!("tracer mode is required"))?;
let msg_tx = self
.tx
.ok_or_else(|| eyre!("tracer event sender is required"))?;
let printer = self.printer.ok_or_else(|| eyre!("printer is required"))?;
let baseline = self
.baseline
.ok_or_else(|| eyre!("baseline process information is required"))?;
let seccomp_bpf = if self.seccomp_bpf == SeccompBpf::Auto {
// TODO: check if the kernel supports seccomp-bpf
// Let's just enable it for now and see if anyone complains
Expand All @@ -131,7 +143,7 @@ impl BuildPtraceTracer for TracerBuilder {
} else {
self.seccomp_bpf
};
let with_tty = match self.mode.as_ref().unwrap() {
let with_tty = match &mode {
TracerMode::Tui(tty) => tty.is_some(),
TracerMode::Log { .. } => true,
};
Expand All @@ -140,24 +152,24 @@ impl BuildPtraceTracer for TracerBuilder {
Tracer {
with_tty,
seccomp_bpf,
msg_tx: self.tx.expect("tracer_tx is required for ptrace tracer"),
msg_tx,
user: self.user,
printer: self.printer.unwrap(),
printer,
modifier_args: self.modifier,
filter: {
let mut filter = self
.filter
.unwrap_or_else(BitFlags::<TracerEventDetailsKind>::all);
trace!("Event filter: {:?}", filter);
if let TracerMode::Log { .. } = self.mode.as_ref().unwrap() {
if let TracerMode::Log { .. } = &mode {
// FIXME: In logging mode, we rely on root child exit event to exit the process
// with the same exit code as the root child. It is not printed in logging mode.
// Ideally we should use another channel to send the exit code to the main thread.
filter |= TracerEventDetailsKind::TraceeExit;
}
filter
},
baseline: self.baseline.unwrap(),
baseline,
req_tx: req_tx.clone(),
polling_interval: {
if self.ptrace_blocking == Some(true) {
Expand All @@ -177,7 +189,7 @@ impl BuildPtraceTracer for TracerBuilder {
}
},
tracee_env: self.tracee_env,
mode: self.mode.unwrap(),
mode,
},
SpawnToken { req_rx, req_tx },
))
Expand Down Expand Up @@ -208,7 +220,7 @@ impl Tracer {
tokio::task::JoinHandle<color_eyre::Result<()>>,
)> {
if !self.req_tx.same_channel(&token.req_tx) {
panic!("The spawn token used does not match the tracer")
bail!("the spawn token does not belong to this tracer");
}
drop(token.req_tx);
let breakpoints = Arc::new(RwLock::new(BTreeMap::new()));
Expand Down Expand Up @@ -243,7 +255,8 @@ impl Tracer {
let result = tokio::runtime::Handle::current()
.block_on(async move { inner.run(args, token.req_rx).await });
if let Err(e) = &result {
tx.send(TracerMessage::FatalError(e.to_string())).unwrap();
// The receiver may have been dropped while the tracer was shutting down.
let _ = tx.send(TracerMessage::FatalError(e.to_string()));
}
result
}
Expand Down
12 changes: 8 additions & 4 deletions crates/tracexec-backend-ptrace/src/ptrace/tracer/inner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1462,8 +1462,10 @@ mod tests {

#[test]
fn test_get_filename_for_display_resolves_proc_self_exe() {
let mut modifier = ModifierArgs::default();
modifier.resolve_proc_self_exe = true;
let modifier = ModifierArgs {
resolve_proc_self_exe: true,
..Default::default()
};
let (inner, _rx) = build_inner(modifier, BitFlags::empty(), SeccompBpf::Off);
let pid = getpid();
let filename = cached_string("/proc/self/exe".to_string());
Expand Down Expand Up @@ -1548,8 +1550,10 @@ mod tests {

#[test]
fn test_timestamp_now_and_seccomp_bpf() {
let mut modifier = ModifierArgs::default();
modifier.timestamp = true;
let modifier = ModifierArgs {
timestamp: true,
..Default::default()
};
let (inner, _rx) = build_inner(modifier, BitFlags::empty(), SeccompBpf::On);
assert!(inner.timestamp_now().is_some());
assert!(inner.seccomp_bpf());
Expand Down
27 changes: 27 additions & 0 deletions crates/tracexec-backend-ptrace/src/ptrace/tracer/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,33 @@ async fn run_exe_and_collect_msgs(

type TracerFixture = (Tracer, UnboundedReceiver<TracerMessage>, SpawnToken);

#[test]
fn build_ptrace_reports_missing_required_configuration() {
let err = TracerBuilder::new()
.build_ptrace()
.err()
.expect("an incomplete builder must fail");
assert!(err.to_string().contains("tracer mode is required"));

let err = TracerBuilder::new()
.mode(TracerMode::Log { foreground: false })
.build_ptrace()
.err()
.expect("an incomplete builder must fail");
assert!(err.to_string().contains("tracer event sender is required"));
}

#[test]
fn spawn_rejects_token_from_another_tracer() {
let (subject, _rx, _token) = tracer(ModifierArgs::default(), SeccompBpf::Off);
let (_other_tracer, _other_rx, other_token) = tracer(ModifierArgs::default(), SeccompBpf::Off);

let err = subject
.spawn(Vec::new(), None, other_token)
.expect_err("a token from another tracer must fail");
assert!(err.to_string().contains("does not belong to this tracer"));
}

#[traced_test]
#[rstest]
#[case(true)]
Expand Down
2 changes: 1 addition & 1 deletion crates/tracexec-core/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ mod tests {
writeln!(out, "Hello world").unwrap();
drop(out);

let content = fs::read_to_string(path.clone()).unwrap();
let content = fs::read_to_string(path).unwrap();
assert!(content.contains("Hello world"));
}

Expand Down
12 changes: 6 additions & 6 deletions crates/tracexec-core/src/cli/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,9 +326,9 @@ inline_format = "%H:%M:%S"
"#;

let cfg: ModifierConfig = toml::from_str(toml_str).unwrap();
assert_eq!(cfg.successful_only.unwrap(), true);
assert_eq!(cfg.stdio_in_cmdline.unwrap(), true);
assert_eq!(cfg.timestamp.as_ref().unwrap().enable, true);
assert!(cfg.successful_only.unwrap());
assert!(cfg.stdio_in_cmdline.unwrap());
assert!(cfg.timestamp.as_ref().unwrap().enable);
assert_eq!(
cfg
.timestamp
Expand Down Expand Up @@ -357,9 +357,9 @@ color_level = "More"
foreground = false
"#;
let cfg: LogModeConfig = toml::from_str(toml_str).unwrap();
assert_eq!(cfg.show_interpreter.unwrap(), true);
assert!(cfg.show_interpreter.unwrap());
assert_eq!(cfg.color_level.unwrap(), ColorLevel::More);
assert_eq!(cfg.foreground.unwrap(), false);
assert!(!cfg.foreground.unwrap());
}

#[test]
Expand All @@ -372,7 +372,7 @@ theme-file = "nord.toml"
theme = { app-title = { fg = "cyan", modifiers = ["bold"] } }
"#;
let cfg: TuiModeConfig = toml::from_str(toml_str).unwrap();
assert_eq!(cfg.follow.unwrap(), true);
assert!(cfg.follow.unwrap());
assert_eq!(cfg.frame_rate.unwrap(), 12.5);
assert_eq!(cfg.max_events.unwrap(), 100);
assert_eq!(cfg.theme_file, Some(PathBuf::from("nord.toml")));
Expand Down
2 changes: 1 addition & 1 deletion crates/tracexec-core/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ mod tests {
path: "/".to_string(),
},
};
let exec_detail = TracerEventDetails::Exec(Box::new(exec_event.clone()));
let exec_detail = TracerEventDetails::Exec(Box::new(exec_event));
assert_eq!(exec_detail.timestamp(), Some(ts));
}

Expand Down
2 changes: 1 addition & 1 deletion crates/tracexec-core/src/event/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ mod tests {
#[test]
fn test_from_arcstr() {
let s: ArcStr = ArcStr::from("hello");
let msg: OutputMsg = s.clone().into();
let msg: OutputMsg = s.into();
assert_eq!(msg.as_ref(), "hello");
}

Expand Down
4 changes: 2 additions & 2 deletions crates/tracexec-core/src/pty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -872,11 +872,11 @@ mod tests {

// give the child a moment to write
std::thread::sleep(Duration::from_millis(100));
reader.read(&mut buf);
let bytes_read = reader.read(&mut buf).unwrap();

eprintln!("buf: {}", String::from_utf8_lossy(&buf));

assert!(buf.windows(5).any(|w| w == b"hello".as_slice()));
assert!(buf[..bytes_read].windows(5).any(|w| w == b"hello"));

// reap child
waitpid(pid, None).unwrap();
Expand Down
3 changes: 1 addition & 2 deletions crates/tracexec-exporter-json/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -386,8 +386,7 @@ mod tests {
fn test_json_result_from_result() {
let ok: JsonResult<u32> = JsonResult::from_result(Ok::<u32, io::Error>(7u32));
assert!(matches!(ok, JsonResult::Success(7)));
let err: JsonResult<u32> =
JsonResult::from_result(Err(io::Error::new(io::ErrorKind::Other, "boom")));
let err: JsonResult<u32> = JsonResult::from_result(Err(io::Error::other("boom")));
assert!(matches!(err, JsonResult::Error(msg) if msg.contains("boom")));
}

Expand Down
2 changes: 1 addition & 1 deletion crates/tracexec-exporter-perfetto/src/packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ mod tests {
);
assert_eq!(
format_cgroup_annotation(&CgroupInfo::Error(CgroupError::CgroupIdNotFound)),
format!("Error: {}", CgroupError::CgroupIdNotFound.to_string())
format!("Error: {}", CgroupError::CgroupIdNotFound)
);
}

Expand Down