From 492f4a6dd23e5644d401ba9f16dadab1c4539efe Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Tue, 16 Nov 2021 10:45:28 +0100 Subject: [PATCH] account for deletion marker in /proc/pid/exe The kernel appends a `` (deleted)`` suffix to the executable path if the original binary has been unlinked since the process was started. The ``pid_of()`` API needs to account for this when matching process names. --- src/daemonfunc.cpp | 53 +++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/daemonfunc.cpp b/src/daemonfunc.cpp index 99f3be8..248a79b 100644 --- a/src/daemonfunc.cpp +++ b/src/daemonfunc.cpp @@ -102,6 +102,40 @@ bool drop_root_privileges(const std::string &username, return true; } +static const char *const EXE_DELETED_MARKER = " (deleted)"; + +/** @brief Remove the deletion marker from a binary name, if applicable. + * + * @param exe Binary name as obtained from ``/proc/$PID/exe``. + * + * @return The input binary name with a trailing `` (deleted)`` removed. + * + * From proc(5): + * + * /proc/[pid]/exe + * […] If the pathname has been unlinked, the symbolic link will + * contain the string '(deleted)' appended to the original pathname. + * + * Which introduces an ambiguity if the path of the actual binary ends in + * `` (deleted)``. + */ +static inline std::string +strip_deleted_marker (const std::string &exe) +{ + if (exe.size () <= sizeof (*EXE_DELETED_MARKER)) { + /* This binary name can’t possibly contain a deleted marker. */ + return exe; + } + + const size_t found = exe.rfind (EXE_DELETED_MARKER); + if (found == std::string::npos) { + /* Input does not contain the deleted marker. */ + return exe; + } + + return exe.substr (0, found); +} + /** * @brief determine the pids for a given program * @param[in] name name (or full path) of the binary @@ -139,21 +173,22 @@ bool pid_of(const std::string& name, std::vector< pid_t >& result) if (!real_exe.empty()) { // we got the path of the exe - if (real_exe == name) + if (real_exe == name || strip_deleted_marker (real_exe) == name) { - result.push_back( pid ); - continue; + result.push_back( pid ); + continue; } - + std::string proc_stat= read_file( base_path + "/stat"); if (proc_stat.empty()) continue; // process vanished - + //TODO some more fuzz tests here?! (cmdline, stat(us)) - - if (basename(real_exe) == name) + + real_exe = basename (real_exe); + if (real_exe == name || strip_deleted_marker (real_exe) == name) { - fuzz2_result.push_back(pid); - continue; + fuzz2_result.push_back(pid); + continue; } } else -- 1.7.1