From 43f7412e746ddc30e89ed74ebe4c0cbbd0f0ac08 Mon Sep 17 00:00:00 2001 From: Tuomas Tynkkynen Date: Wed, 19 Feb 2025 01:48:00 +0200 Subject: [PATCH] process_matcher: Fix accidentally matching against pid Currently pgrep/pkill without -x/-f flags is matching based on the first 15 characters of /proc//stat, which actually contains something like "1116878 (cat) R" thus matching the process id when it should just match on the name. This has probably come from misunderstanding the comment from manpage: > The process name used for matching is limited to the 15 characters > present in the output of /proc/pid/stat. ... which doesn't mean pgrep/pkill is literally matching on 15 characters of /proc//stat but that the process name in that file is truncated to 15 characters. Fixes #307 --- src/uu/pgrep/src/process_matcher.rs | 12 +++--------- tests/by-util/test_pgrep.rs | 7 +++++++ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/uu/pgrep/src/process_matcher.rs b/src/uu/pgrep/src/process_matcher.rs index 7e3ca24..ffb2474 100644 --- a/src/uu/pgrep/src/process_matcher.rs +++ b/src/uu/pgrep/src/process_matcher.rs @@ -160,18 +160,12 @@ fn collect_matched_pids(settings: &Settings) -> Vec { name.into() }; let pattern_matched = { - let want = if settings.exact { - // Equals `Name` in /proc//status - // The `unwrap` operation must succeed - // because the REGEX has been verified as correct in `uumain`. - &name - } else if settings.full { + let want = if settings.full { // Equals `cmdline` in /proc//cmdline &pid.cmdline } else { - // From manpage: - // The process name used for matching is limited to the 15 characters present in the output of /proc/pid/stat. - &pid.proc_stat()[..15] + // Equals `Name` in /proc//status + &name }; settings.regex.is_match(want) diff --git a/tests/by-util/test_pgrep.rs b/tests/by-util/test_pgrep.rs index 0f33494..f4f9314 100644 --- a/tests/by-util/test_pgrep.rs +++ b/tests/by-util/test_pgrep.rs @@ -369,6 +369,13 @@ fn test_invalid_signal() { .stderr_contains("Unknown signal 'foo'"); } +#[test] +#[cfg(target_os = "linux")] +fn test_does_not_match_pid() { + let our_pid = std::process::id(); + new_ucmd!().arg(our_pid.to_string()).fails(); +} + #[test] #[cfg(target_os = "linux")] fn test_too_long_pattern() {