Skip to content

Commit

Permalink
LinuxProcessList_recurseProcTree: open dirfd first
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
tanriol authored and BenBE committed May 5, 2022
1 parent e08eec8 commit e07fce7
Showing 1 changed file with 8 additions and 8 deletions.
16 changes: 8 additions & 8 deletions linux/LinuxProcessList.c
Original file line number Diff line number Diff line change
Expand Up @@ -1446,22 +1446,22 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
if (parent && pid == parent->pid)
continue;

bool preExisting;
Process* proc = ProcessList_getProcess(pl, pid, &preExisting, LinuxProcess_new);
LinuxProcess* lp = (LinuxProcess*) proc;

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;
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;

proc->tgid = parent ? parent->pid : pid;
proc->isUserlandThread = proc->pid != proc->tgid;

LinuxProcessList_recurseProcTree(this, procFd, "task", proc, period);

/*
Expand Down

0 comments on commit e07fce7

Please sign in to comment.