14758ebc8f
readeither() caches (in new_p) a pointer to the proc_t of a task-group leader, but readeither()'s callers can do pretty much anything with the proc_t structure passed to and/or returned by this function. For example, they can 1/ free it or 2/ recycle it (by passing it to readeither() as x). 1/ leads to a use-after-free, and 2/ leads to unexpected behavior when taskreader()/simple_readtask() is called with new_p equal to x (this is not a theoretical flaw: 2/ happens in readproctab3() when want_task() returns false and p is a group leader). As a workaround, we keep a copy of new_p's first member (tid) in static storage, and the next times we enter readeither() we check this "canary" against the tid in new_p: if they differ, we reset new_p to NULL, which forces the allocation of a new proc_t (the new "leader", or reference). This always detects 2/ (because free_acquired(x,1) memsets x and hence new_p); always detects 1/ if freed via free_acquired() and/or freeproc() (very likely, otherwise memory may be leaked); probably detects 1/ even if freed directly via free() (because the canary is the first member of proc_t, likely to be overwritten by free()); but can not detect 1/ if free() does not write to new_p's chunk at all. Moreover, accessing new_p->tid to check the canary in case 1/ is itself a use-after-free, so a better long-term solution should be implemented at some point (we wanted to avoid intrusive and backward-incompatible changes in this library function, hence this imperfect workaround). |
||
---|---|---|
.. | ||
alloc.c | ||
alloc.h | ||
COPYING | ||
devname.c | ||
devname.h | ||
escape.c | ||
escape.h | ||
fprocopen.3 | ||
libprocps.pc.in | ||
libprocps.sym | ||
numa.c | ||
numa.h | ||
openproc.3 | ||
procps-private.h | ||
procps.h | ||
pwcache.c | ||
pwcache.h | ||
readproc.3 | ||
readproc.c | ||
readproc.h | ||
readproctab.3 | ||
sig.c | ||
sig.h | ||
slab.c | ||
slab.h | ||
sysinfo.c | ||
sysinfo.h | ||
version.c | ||
version.h | ||
wchan.c | ||
wchan.h | ||
whattime.c | ||
whattime.h |