Skip to content

Commit

Permalink
Linux: reorder /proc/<pid>/status parsing
Browse files Browse the repository at this point in the history
When parsing an essential pid entry file like 'status' fails, we treat
the process as a short-lived one and skip adding it into the process
table.

This should be done before the process is added, as the goto label used
for error handling can free the process structure, thus causing an
use-after-free scenario.

Fixes: 22d25db ("Linux: detect container process by different PID namespace")
Closes: #1455
  • Loading branch information
cgzones authored and BenBE committed May 17, 2024
1 parent 314d693 commit 66f0ba0
Showing 1 changed file with 27 additions and 26 deletions.
53 changes: 27 additions & 26 deletions linux/LinuxProcessTable.c
Original file line number Diff line number Diff line change
Expand Up @@ -1571,6 +1571,32 @@ static bool LinuxProcessTable_recurseProcTree(LinuxProcessTable* this, openat_ar
if (!LinuxProcessTable_updateUser(host, proc, procFd, mainTask))
goto errorReadingProcess;

/* Check if the process is inside a different PID namespace. */
if (proc->isRunningInContainer == TRI_INITIAL && rootPidNs != (ino_t)-1) {
struct stat sb;
#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT)
int res = fstatat(procFd, "ns/pid", &sb, 0);
#else
char path[PATH_MAX];
xSnprintf(path, sizeof(path), "%s/ns/pid", procFd);
int res = stat(path, &sb);
#endif
if (res == 0) {
proc->isRunningInContainer = (sb.st_ino != rootPidNs) ? TRI_ON : TRI_OFF;
}
}

if (ss->flags & PROCESS_FLAG_LINUX_CTXT
|| ((hideRunningInContainer || ss->flags & PROCESS_FLAG_LINUX_CONTAINER) && proc->isRunningInContainer == TRI_INITIAL)
#ifdef HAVE_VSERVER
|| ss->flags & PROCESS_FLAG_LINUX_VSERVER
#endif
) {
proc->isRunningInContainer = TRI_OFF;
if (!LinuxProcessTable_readStatusFile(proc, procFd))
goto errorReadingProcess;
}

if (!preExisting) {

#ifdef HAVE_OPENVZ
Expand Down Expand Up @@ -1604,32 +1630,6 @@ static bool LinuxProcessTable_recurseProcTree(LinuxProcessTable* this, openat_ar
}
}

/* Check if the process in inside a different PID namespace. */
if (proc->isRunningInContainer == TRI_INITIAL && rootPidNs != (ino_t)-1) {
struct stat sb;
#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT)
int res = fstatat(procFd, "ns/pid", &sb, 0);
#else
char path[4096];
xSnprintf(path, sizeof(path), "%s/ns/pid", procFd);
int res = stat(path, &sb);
#endif
if (res == 0) {
proc->isRunningInContainer = (sb.st_ino != rootPidNs) ? TRI_ON : TRI_OFF;
}
}

if (ss->flags & PROCESS_FLAG_LINUX_CTXT
|| ((hideRunningInContainer || ss->flags & PROCESS_FLAG_LINUX_CONTAINER) && proc->isRunningInContainer == TRI_INITIAL)
#ifdef HAVE_VSERVER
|| ss->flags & PROCESS_FLAG_LINUX_VSERVER
#endif
) {
proc->isRunningInContainer = TRI_OFF;
if (!LinuxProcessTable_readStatusFile(proc, procFd))
goto errorReadingProcess;
}

/*
* Section gathering non-critical information that is independent from
* each other.
Expand Down Expand Up @@ -1759,6 +1759,7 @@ static bool LinuxProcessTable_recurseProcTree(LinuxProcessTable* this, openat_ar
*/
} else {
/* A really short-lived process that we don't have full info about */
assert(ProcessTable_findProcess(pt, Process_getPid(proc)) == NULL);
Process_delete((Object*)proc);
}
}
Expand Down

0 comments on commit 66f0ba0

Please sign in to comment.