From e07fce701433f79f925eef66508d1ada53ce5d53 Mon Sep 17 00:00:00 2001 From: Denis Lisov Date: Mon, 14 Feb 2022 00:32:28 +0300 Subject: [PATCH] LinuxProcessList_recurseProcTree: open dirfd first A process can die between reading the directory listing and opening the directory FD (if HAVE_OPENAT) or /proc files (otherwise) for reading the process data. This race would cause LinuxProcessList_recurseProcTree to remove it from the list immediately, which is unexpected in the "highlight dying processes" mode and can break the tree structure. This patch closes this race in the HAVE_OPENAT case by only accessing the process entry after the directory FD has been opened. --- linux/LinuxProcessList.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c index e23af209..0d4be558 100644 --- a/linux/LinuxProcessList.c +++ b/linux/LinuxProcessList.c @@ -1446,6 +1446,15 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_ if (parent && pid == parent->pid) continue; +#ifdef HAVE_OPENAT + int procFd = openat(dirFd, entry->d_name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW); + if (procFd < 0) + continue; +#else + char procFd[4096]; + xSnprintf(procFd, sizeof(procFd), "%s/%s", dirFd, entry->d_name); +#endif + bool preExisting; Process* proc = ProcessList_getProcess(pl, pid, &preExisting, LinuxProcess_new); LinuxProcess* lp = (LinuxProcess*) proc; @@ -1453,15 +1462,6 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_ proc->tgid = parent ? parent->pid : pid; proc->isUserlandThread = proc->pid != proc->tgid; -#ifdef HAVE_OPENAT - int procFd = openat(dirFd, entry->d_name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW); - if (procFd < 0) - goto errorReadingProcess; -#else - char procFd[4096]; - xSnprintf(procFd, sizeof(procFd), "%s/%s", dirFd, entry->d_name); -#endif - LinuxProcessList_recurseProcTree(this, procFd, "task", proc, period); /*