Skip to content

Commit 66f0ba0

Browse files
cgzonesBenBE
authored andcommitted
Linux: reorder /proc/<pid>/status parsing
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
1 parent 314d693 commit 66f0ba0

File tree

1 file changed

+27
-26
lines changed

1 file changed

+27
-26
lines changed

linux/LinuxProcessTable.c

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,6 +1571,32 @@ static bool LinuxProcessTable_recurseProcTree(LinuxProcessTable* this, openat_ar
15711571
if (!LinuxProcessTable_updateUser(host, proc, procFd, mainTask))
15721572
goto errorReadingProcess;
15731573

1574+
/* Check if the process is inside a different PID namespace. */
1575+
if (proc->isRunningInContainer == TRI_INITIAL && rootPidNs != (ino_t)-1) {
1576+
struct stat sb;
1577+
#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT)
1578+
int res = fstatat(procFd, "ns/pid", &sb, 0);
1579+
#else
1580+
char path[PATH_MAX];
1581+
xSnprintf(path, sizeof(path), "%s/ns/pid", procFd);
1582+
int res = stat(path, &sb);
1583+
#endif
1584+
if (res == 0) {
1585+
proc->isRunningInContainer = (sb.st_ino != rootPidNs) ? TRI_ON : TRI_OFF;
1586+
}
1587+
}
1588+
1589+
if (ss->flags & PROCESS_FLAG_LINUX_CTXT
1590+
|| ((hideRunningInContainer || ss->flags & PROCESS_FLAG_LINUX_CONTAINER) && proc->isRunningInContainer == TRI_INITIAL)
1591+
#ifdef HAVE_VSERVER
1592+
|| ss->flags & PROCESS_FLAG_LINUX_VSERVER
1593+
#endif
1594+
) {
1595+
proc->isRunningInContainer = TRI_OFF;
1596+
if (!LinuxProcessTable_readStatusFile(proc, procFd))
1597+
goto errorReadingProcess;
1598+
}
1599+
15741600
if (!preExisting) {
15751601

15761602
#ifdef HAVE_OPENVZ
@@ -1604,32 +1630,6 @@ static bool LinuxProcessTable_recurseProcTree(LinuxProcessTable* this, openat_ar
16041630
}
16051631
}
16061632

1607-
/* Check if the process in inside a different PID namespace. */
1608-
if (proc->isRunningInContainer == TRI_INITIAL && rootPidNs != (ino_t)-1) {
1609-
struct stat sb;
1610-
#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT)
1611-
int res = fstatat(procFd, "ns/pid", &sb, 0);
1612-
#else
1613-
char path[4096];
1614-
xSnprintf(path, sizeof(path), "%s/ns/pid", procFd);
1615-
int res = stat(path, &sb);
1616-
#endif
1617-
if (res == 0) {
1618-
proc->isRunningInContainer = (sb.st_ino != rootPidNs) ? TRI_ON : TRI_OFF;
1619-
}
1620-
}
1621-
1622-
if (ss->flags & PROCESS_FLAG_LINUX_CTXT
1623-
|| ((hideRunningInContainer || ss->flags & PROCESS_FLAG_LINUX_CONTAINER) && proc->isRunningInContainer == TRI_INITIAL)
1624-
#ifdef HAVE_VSERVER
1625-
|| ss->flags & PROCESS_FLAG_LINUX_VSERVER
1626-
#endif
1627-
) {
1628-
proc->isRunningInContainer = TRI_OFF;
1629-
if (!LinuxProcessTable_readStatusFile(proc, procFd))
1630-
goto errorReadingProcess;
1631-
}
1632-
16331633
/*
16341634
* Section gathering non-critical information that is independent from
16351635
* each other.
@@ -1759,6 +1759,7 @@ static bool LinuxProcessTable_recurseProcTree(LinuxProcessTable* this, openat_ar
17591759
*/
17601760
} else {
17611761
/* A really short-lived process that we don't have full info about */
1762+
assert(ProcessTable_findProcess(pt, Process_getPid(proc)) == NULL);
17621763
Process_delete((Object*)proc);
17631764
}
17641765
}

0 commit comments

Comments
 (0)