[PATCH] utils: fix check_pid_path to work with deleted file as well

Karel Kočí karel.koci at nic.cz
Thu Jul 2 06:49:56 EDT 2020

check_pid_patch is checking if process with given PID and executable
path is running. If this code fails the rest of the code can be
convinced that program is no longer running and possibly spawns new
instance that can collide with already running one. This behavior was
reproduced with hostapd.

Symbolic link exe in process subdirectory in /proc points to original
executable. The problem is that it reads as original path plus string
' (deleted)' if file is removed. The process is still running but
original file is no longer available on files system.

This behavior is triggered not only when file is removed (unlinked) but
also when file is replaced. This happens clearly on package update. In
general this happens any time all references (hard links) to file are
removed from file system.

This is not ultimate fix as exe link points to any last reference on
file system with preference for original one. The problem is if there
are multiple references and the original one is removed. This can be
reproduced just by copying executable (hard linking) and unlinking the
original one. In such case exe link would point to copy and not to
original deleted one.

Signed-off-by: Karel Kočí <karel.koci at nic.cz>
 utils.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/utils.c b/utils.c
index ba26952..4f40b4b 100644
--- a/utils.c
+++ b/utils.c
@@ -176,6 +176,8 @@ crc32_file(FILE *fp)
 bool check_pid_path(int pid, const char *exe)
+	const char deleted[] = " (deleted)";
+	const int deleted_len = strlen(deleted);
 	int proc_exe_len;
 	int exe_len = strlen(exe);
@@ -191,10 +193,13 @@ bool check_pid_path(int pid, const char *exe)
 	proc_exe_len = readlink(proc_exe, proc_exe_buf, exe_len);
-	if (proc_exe_len != exe_len)
+	if (proc_exe_len == exe_len)
+		return !memcmp(exe, proc_exe_buf, exe_len);
+	else if (proc_exe_len == exe_len + deleted_len)
+		return !memcmp(exe, proc_exe_buf, exe_len) &&
+			!memcmp(exe + exe_len, deleted, deleted_len);
+	else
 		return false;
-	return !memcmp(exe, proc_exe_buf, exe_len);
 static const char * const uci_validate_name[__BLOBMSG_TYPE_LAST] = {

More information about the openwrt-devel mailing list