Date: Sun, 18 Jun 2023 21:23:06 -0700 From: Mark Millard <marklmi@yahoo.com> To: FreeBSD Hackers <freebsd-hackers@freebsd.org> Subject: top vs. array sorted_state's out of bounds indexing (and related issues) Message-ID: <DA51FDC7-EAF0-486E-9A85-22044D621E7D@yahoo.com> References: <DA51FDC7-EAF0-486E-9A85-22044D621E7D.ref@yahoo.com>
next in thread | previous in thread | raw e-mail | index | archive | help
usr.bin/top/machine.c (from main) has: /* . . . The process states are ordered as follows (from least * to most important): WAIT, zombie, sleep, stop, start, run. The * array declaration below maps a process state index into a number * that reflects this ordering. */ static int sorted_state[] = { 0, /* not used */ 3, /* sleep */ 1, /* ABANDONED (WAIT) */ 6, /* run */ 5, /* start */ 2, /* zombie */ 4 /* stop */ }; Note the elements are 0..6, so 7 elements. It is accessed via code like: sorted_state[(unsigned char)(b)->ki_stat] But ->ki_stat has the values listed in sys/sys/proc.h : /* * These were process status values (p_stat), now they are only used in * legacy conversion code. */ #define SIDL 1 /* Process being created by fork. */ #define SRUN 2 /* Currently runnable. */ #define SSLEEP 3 /* Sleeping on an address. */ #define SSTOP 4 /* Process debugging or suspension. */ #define SZOMB 5 /* Awaiting collection by parent. */ #define SWAIT 6 /* Waiting for interrupt. */ #define SLOCK 7 /* Blocked on a lock. */ This leads to element indexes (including the "unused" 0) of 0..7 so spanning 8 elements. Thus there is a out of bounds error involved when ->ki_stat == SLOCK . (I later show the ki_stat assignments.) There is also the issue that: SIDL is misidentified as: sleep SRUN is misidentified as: ABANDONED (WAIT) SSLEEP is misidentified as: run SZOMB is misidentified as: start SWAIT is misidentified as: zombie SLOCK is out of bounds (as indicated above). So the sort order in top is not as documented. For reference, from sys/kern/kern_proc.c : if (p->p_state == PRS_NORMAL) { /* approximate. */ if (TD_ON_RUNQ(td) || TD_CAN_RUN(td) || TD_IS_RUNNING(td)) { kp->ki_stat = SRUN; } else if (P_SHOULDSTOP(p)) { kp->ki_stat = SSTOP; } else if (TD_IS_SLEEPING(td)) { kp->ki_stat = SSLEEP; } else if (TD_ON_LOCK(td)) { kp->ki_stat = SLOCK; } else { kp->ki_stat = SWAIT; } } else if (p->p_state == PRS_ZOMBIE) { kp->ki_stat = SZOMB; } else { kp->ki_stat = SIDL; } === Mark Millard marklmi at yahoo.com
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?DA51FDC7-EAF0-486E-9A85-22044D621E7D>